哈希

两数之和

  1. 暴力求解方法略,两个for

  2. 哈希表方法
    #include <uthash.h>

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */


struct hashTable{
    int key;
    int val;
    UT_hash_handle hh;
}

struct hashTable* hashTable;

struct hashTable* find(int ikey){
    struct hashTable* tmp;
    HASH_FIND_INT(hashTable, &ikey, tmp);
    retrun tmp;
}

void insert(int ikey, int ival){
    struct hashTable* it = find(ikey);
    if(it == NULL){
        struct hashTable* tmp = malloc(sizeof(struct hashTable));
        tmp->key = ikey, tmp->val = ival;
        HASH_ADD_INT(hashTable,key,tmp);
    }else{
        it->val = ival;
    }
}

int* twoSum(int* nums, int numsSize, int target, int* returnSize) {
    hashTable = NULL;
    for(int i=0;i<numsSize;i++){
        struct hashTable* it = find(target-nums[i]);
        if(it != NULL){
            int* ret = malloc(sizeof(int)*2);
            ret[0]=it->val,ret[1]=i;
            *returnSize = 2;
            return ret;
        }
        insert(nums[i],i);
    }
    *returnSize = 0;
    return NULL;
}

字母异位词分组

太难了,不看。。

最长连续序列

依次读取数字,加入哈希表
遍历哈希表,如果有x-1,则跳过。
否则,循环找x+1,取最大长度。

struct HashEntry{
    int key;
    UT_hash_handle hh;
};

int longestConsecutive(int* nums, int numsSize) {
    struct HashEntry* hashSet = NULL;
    struct HashEntry* e;

    for(int i=0;i<numsSize;i++){
        HASH_FIND_INT(hashSet, &nums[i],e);
        if(e == NULL){
            e = malloc(sizeof(struct HashEntry));
            e->key = nums[i];
            HASH_ADD_INT(hashSet, key, e);
        }
    }

    int ans = 0;
    struct HashEntry* next;
    HASH_ITER(hh, hashSet,e,next){
        int x = e->key;
        int y = x-1;
        HASH_FIND_INT(hashSet, &y, e);
        if(e){
            continue;
        }
        y = x;
        do {
            y++;
            HASH_FIND_INT(hashSet, &y, e);
        }while(e);

        ans = fmax(ans, y-x);
    }

    HASH_CLEAR(hh, hashSet);
    return ans;
}

双指针

移动零

个人做法
0移到最后,其余数字往前移。

void moveZeroes(int* nums, int numsSize) {
    int end = numsSize-1;
    int start = 0;
    for(int i=0;i<=end;i++){
        if(nums[i] == 0){
            for(int j=i;j<end;j++){
                nums[j] = nums[j+1];
            }
            nums[end] = 0;
            i--;
            end--;
        }
    }
    
}

双指针做法

左指针指向当前已经处理好的序列的尾部。左指针左边均为非零数;
右指针指向待处理序列的头部。右指针左边直到左指针处均为零。

void swap(int *a, int *b){
    int t = *a;
    *a = *b, *b = t;
}


void moveZeroes(int* nums, int numsSize) {
    int left = 0, right = 0;
    while(right < numsSize){
        if(nums[right]){
            swap(nums + left, nums + right);
            left++;
        }
        right++;
    }

    
}

盛最多水的容器

指针指向两端,当移动长的那根时,容量不会增大。
所以移动小的那根,不会漏掉更大的容量。
最后比较,取最大。

int maxArea(int* height, int heightSize) {
    int start = 0, end = heightSize-1;
    int max = 0;
    while(start!=end){
        int v = (end-start)*fmin(height[start],height[end]);
        max = fmax(v,max);
        if(height[start]<height[end]){
            start++;
        }else{
            end--;
        }

    }
    return max;
}

二叉树

二叉树的中序遍历

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
void inorder(struct TreeNode* root, int* res, int* resSize){
    if(root!=NULL){
        inorder(root->left,res,resSize);
        res[(*resSize)++] = root->val;
        inorder(root->right,res,resSize);
    }
}

int* inorderTraversal(struct TreeNode* root, int* returnSize) {
    int* res = malloc(sizeof(int)*100);
    *returnSize = 0;
    inorder(root, res, returnSize);
    return res;
}

二叉树的最大深度

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
int maxDepth(struct TreeNode *root) {
    if (root == NULL) return 0;
    return fmax(maxDepth(root->left), maxDepth(root->right)) + 1;
}

翻转二叉树

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
struct TreeNode* invertTree(struct TreeNode* root) {
    if(root == NULL){
        return NULL;
    }
    
    struct TreeNode* left = invertTree(root->left);
    struct TreeNode* right = invertTree(root->right);
    root->left = right;
    root->right = left;
    return root;
}

对称二叉树

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

bool check(struct TreeNode* p,struct TreeNode* q){
    if(!p && !q) return true; //两个节点都不存在
    if(!p || !q) return false;//有一个节点不存在
    return p->val == q->val && check(p->left, q->right) && check(p->right, q->left);
}
bool isSymmetric(struct TreeNode* root) {
    return check(root->left, root->right);
}

二叉树的直径

同求二叉树深度,在代码中增加取左右子树深度和的最大值。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

int ans;
int depth(struct TreeNode* root){
    if(root == NULL){
        return 0;
    }

    int L = depth(root->left);
    int R = depth(root->right);

    ans = fmax(ans, L+R);
    return fmax(L,R)+1;
}

int diameterOfBinaryTree(struct TreeNode* root) {
    ans = 0;
    depth(root);
    return ans;
}

技巧

只出现一次的数字

异或运算,偶数次出现的数字都被消除。

int singleNumber(int* nums, int numsSize) {
    int single = 0;
    for(int i=0;i<numsSize;i++){
        single ^= nums[i];
    }
    return single;
}

多数元素

方法一:排序后,去中值

使用快速排序

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


int majorityElement(int* nums, int numsSize) {
    qsort(nums, numsSize,sizeof(int),cmp);
    return nums[numsSize/2];
}

方法二:同归于尽消杀法

https://leetcode.cn/problems/majority-element/solutions/3043071/duo-shu-yuan-su-by-magical-vvingxna-qtgz

int majorityElement(int* nums, int numsSize) {
    int flag=nums[0];
    int flagnum=0;
    int i=0;
    while(i<numsSize){
        if(nums[i]==flag){
            flagnum++;
        }else{
            if(flagnum==0){
                flag=nums[i];
                flagnum++;
            }else{
                flagnum--;
            }
        }
        i++;
    }
    return flag;
}