数据结构-数组


217、存在重复数字

给你一个整数数组 nums 。如果任一值在数组中出现至少两次 ,返回 true ;如果数组中每个元素互不相同,返回 false 。

输入:nums = [1,2,3,1]
输出:true

方法1:

bool containsDuplicate(int* nums, int numsSize)
{
    int i,j;
    int sign = 0;
    for(i = 0; i < numsSize; i++)
    {
        for(j=i+1;j

超出时间限制了,时间复杂度 n^2

方法2:
c库函数qsort()

void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*))
base:要排序的数组第一个元素的指针
nitems: 数组的元素的个数
size:一个元素的大小
compar:比较数组中的两个元素。

int cmpfunc (const void * a, const void * b)
{
   return ( *(int*)a - *(int*)b );
}

等于

int p=*(int*)a;
int q=*(int*)b;
return p-q;
int cmp(const void* _a, const void* _b) {
    int a = *(int*)_a, b = *(int*)_b;
    return a - b;
}

bool containsDuplicate(int* nums, int numsSize) {
    qsort(nums, numsSize, sizeof(int), cmp);
    for (int i = 0; i < numsSize - 1; i++) {
        if (nums[i] == nums[i + 1]) {
            return true;
        }
    }
    return false;
}

方法3:
哈希表

#define HASHCAPACITY 769
int repeatnumber=0;

struct List{
    long int value;
    struct List *next;
};
typedef struct{
    struct List* data;
}Hash;

int hashFunc(int key)
{
    if(key<0)
    {
      return -key%HASHCAPACITY;//you need care about "negative number"
    }

        /*beacuse the range of the hash table is [0,HASHCAPACITY-1]*/
        /*if you don't use "if(key<0)",it will create error:"heap-buffer-overflow"*/

    else
        return key%HASHCAPACITY;
}
void ListPush(struct List *head,int key){
    struct List* temp=(struct List*)malloc(sizeof(struct List));
    temp->value=key;
    temp->next=head->next;
    head->next=temp;
}
bool ListContains(struct List* head,int key){
    struct List* temp=head;
    for(;temp->next!=NULL;temp=temp->next)
    {
        if(temp->next->value==key)
            return true;
    }
    return false;
}

Hash* HashInitilize()
{
    Hash *h=(Hash*)malloc(sizeof(Hash));
    h->data=(struct List*)malloc(HASHCAPACITY *sizeof(struct List)); 
    for(int i=0;idata[i].next=NULL;
        h->data[i].value=10000000001;
    }  
    return h;
}
bool HashPush(Hash* object,int key)
{
    int keyvalue=hashFunc(key);
    if(object!=NULL &&!ListContains(&(object->data[keyvalue]),key))
    {
         ListPush(&(object->data[keyvalue]),key);
         
         return 1;
    }
    if(object==NULL)
        printf("object id NULL\n");
    return 0;
   
}
void HashFree(Hash*object)
{
    if(object==NULL)
        return;
    for(int i=0;idata[i].next)
        {
            struct List* temp=object->data[i].next;
            object->data[i].next=temp->next;
            free(temp);
        }
        free(object->data);
    }
}

bool containsDuplicate(int* nums, int numsSize){
    int i;
    int m=0;
    Hash* hashtable=HashInitilize();
   // hashtable=(Hash*)malloc(sizeof(Hash));   // !!!!cause memory leaks
    
    for(i=0;i

use after free:访问堆上被释放的内存
heap buffer overflow:堆上缓冲区访问溢出
stack buffer overflow:栈上缓冲区访问溢出
global buffer overflow:全局缓冲区访问溢出
use after return:访问栈上已被释放的内存

53最大子数组和

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

方法1:暴力求解。超出时间限制。

int maxSubArray(int* nums, int numsSize){
    int i=0,j=0;
    int sum=nums[0];
    int largestSum=nums[0];
    for(;isum?largestSum:sum;
        for(j=i+1;jsum?largestSum:sum;
        }
    }
    return largestSum;
}

方法2:贪心算法

出错的地方:while(nums[i]!=NULL),此时的nums[i]是个整型的数,不能用NULL表示。可以写Nums!=NULL,因为nums是个指针

//贪心算法:若当前的元素之和小于0,则丢弃当前元素之前的数列

/*Greedy algorithm:If the sum of the current element is less than 0, the sequence of the current element is discarded.*/
int maxSubArray(int* nums, int numsSize){
    if(nums==NULL)
        return 0;
    int sum=0;
    int i=0;
    int max=-10000;
    while(imax?sum:max;
        i++;
    }
    return max;
}

方法3:动态规划

//动态规划:如果前一个元素大于0,则把他加到当前元素
/*Dynamic programming:If the previous element is greater than 0,
it is added to the current element.*/
int maxSubArray(int* nums, int numsSize){
    int max=nums[0];
    int i;
    for(i=0;i0)
        {
            nums[i+1]=nums[i]+nums[i+1];
        }
    }
    for(i=0;inums[i]?max:nums[i];
    }
    return max;
}

方法4:分治法
对于一个区间 [l,r][l,r],我们取 m = (r-l)/2+l;对区间 [l,m][l,m] 和 [m+1,r][m+1,r] 分治求解。当递归逐层深入直到区间长度缩小为 1 的时候,递归「开始回升」。这个时候我们考虑如何通过 [l,m][l,m] 区间的信息和 [m+1,r][m+1,r] 区间的信息合并成区间 [l,r][l,r] 的信息。

/***********partition*******************/
struct status
{
    int isum,lsum,rsum,msum;
    //isum:the sum of the current sequence within [l,r]
    //lsum:the largest sum of the sequence containing the left end point within [l,r]
    //rsum:the largest sum of the sequence containg the right end point within [l,r]
    //msum:the largest sum of the sequence within [l,r]
};

struct status recursion(struct status left,struct status right)
{
    int isum=left.isum+right.isum;
    int lsum=fmax(left.lsum,left.isum+right.lsum);
    int rsum=fmax(right.rsum,right.isum+left.rsum);
    int msum=fmax(fmax(left.msum,right.msum),left.rsum+right.lsum);

    struct status ret={isum,lsum,rsum,msum};
    return ret;
}

struct status get(int *a,int start,int end)
{
    if(start==end)
        return (struct status) {a[start],a[start],a[start],a[start]};
        
    int middle=(end-start)/2+start;

    struct status left=get(a,start,middle);
    struct status right=get(a,middle+1,end);
    return recursion(left,right);
}
int maxSubArray(int* nums, int numsSize){
    return get(nums,0,numsSize-1).msum;
}

1两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
 /************哈希表*****************/
# define NULLKEY 100000001

struct Lnode
{
    int val;
    int keyAddr;
};
typedef struct
{
    struct Lnode *elem;
    int count;

}hashTable;//build a hash table of directly determining address 

void initHashTable(hashTable *H,int HASHSIZE)
{
    int i;
    H->count = HASHSIZE;
    
    H->elem = (struct Lnode *) malloc (sizeof(struct Lnode) * HASHSIZE);
    for(i=0; i < HASHSIZE; i++)
    {
        H->elem[i].val = NULLKEY;
        H->elem[i].keyAddr=-1;
    }
   
}

int hashFunc(int key,int HASHSIZE)
{
    if(key<0)   return -key % HASHSIZE;
    else        return key % HASHSIZE;
}

int insertAndSearchValue(hashTable *H, int key,int keyaddr,int target,int HASHSIZE)
{
    int addr = hashFunc(key,HASHSIZE);

    //when we insert "key",see if "target-key" exists.
    for(int i=0; i < HASHSIZE; i++)
    {
        if(H->elem[i].val == target-key)
        {
            return H->elem[i].keyAddr;
        }
    }

    while(H->elem[addr].val != NULLKEY)
    {
        addr = (addr+1) % HASHSIZE;
    }

    H->elem[addr].val = key;
    H->elem[addr].keyAddr = keyaddr;
    return -1;
}

int* twoSum(int* nums, int numsSize, int target, int* returnSize)
{
    hashTable *H=(hashTable*)malloc(sizeof(hashTable));
    initHashTable(H,numsSize);
    int *ret = (int *) malloc (sizeof(int) * 2);

    for(int j=0; j

void sortArray(int *nums, int numsSize)
{
    int i,j;
    for(i=0; i i ; j--)
        {
            if(nums[j]
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n)
{
    while(n>0)
    {
        if(m>0 && nums1[m-1] > nums2[n-1])
        {
            nums1[--nums1Size] = nums1[--m];
        }
        else
        {
            nums1[--nums1Size] = nums2[--n];
        }
    }
}