【leetcode】c语言题解集合 随时更新

常用排序、搜索算法(BFS,DFS)、递归、分治、最优化算法

/*
242. 有效的字母异位词
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。

示例 1:

输入: s = "anagram", t = "nagaram"
输出: true
示例 2:

输入: s = "rat", t = "car"
输出: false
说明:
你可以假设字符串只包含小写字母。
*/
//4 ms	7.1 MB
bool isAnagram(char * s, char * t){
    int lens = strlen(s);
    int lent = strlen(t);
    if(lens != lent) {
        return false;
    }
    
    int dp[256] = {0};
    for(int i = 0; i < lens; i++) {
        dp[s[i]]++;
    }
    for(int i = 0; i < lent; i++) {
        dp[t[i]]--;
    }
    
    for(int i = (int)'a'; i <= (int)'z'; i++) {
        if(dp[i]) {
            return false;
        }    
    }
    return true;
}

//28 ms	7.3 MB
int cmp(const char *a, const char *b)
{
    return *a - *b;
}

bool isAnagram(char * s, char * t){
    int lens = strlen(s);
    int lent = strlen(t);
    if(lens != lent) {
        return false;
    }
    
    qsort(s, lens, sizeof(char), cmp);
    qsort(t, lent, sizeof(char), cmp);
    
    if(strcmp(s, t) == 0) {
        return true;
    }
    return false;
}


/*
349. 两个数组的交集
给定两个数组,编写一个函数来计算它们的交集。

示例 1:

输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2]
示例 2:

输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出: [9,4]
说明:

输出结果中的每个元素一定是唯一的。
我们可以不考虑输出结果的顺序。
*/
#define MAX(a, b) ((a) > (b) ? (a) : (b))
int cmp(const int *a, const int *b)
{
    return *a - *b;
}
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* intersection(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){
    if(nums1Size == 0 || nums2Size == 0 || nums1 == NULL || nums2 == NULL) {
        *returnSize = 0;
        return NULL;
    }
    
    int* res = (int*)malloc(sizeof(int) * MAX(nums1Size, nums2Size));
    qsort(nums1, nums1Size, sizeof(int), cmp);
    qsort(nums2, nums2Size, sizeof(int), cmp);
    
    int left1 = 0;
    int left2 = 0;
    *returnSize = 0;
    while(left1 < nums1Size && left2 < nums2Size) {
        if(nums1[left1] == nums2[left2]) {
            int tmp = nums1[left1];
            res[(*returnSize)++] = tmp;
            while(left1 < nums1Size && nums1[left1] == tmp) {
                left1++;
            }
            while(left2 < nums2Size && nums2[left2] == tmp) {
                left2++;
            }
        } else if(nums1[left1] < nums2[left2]) {
            left1++;
        } else {
            left2++;
        }
    }
    
    return res;
}


/*
350. 两个数组的交集 II
给定两个数组,编写一个函数来计算它们的交集。

示例 1:

输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2,2]
示例 2:

输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出: [4,9]
说明:

输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致。
我们可以不考虑输出结果的顺序。
*/
#define MAX(a, b) ((a) > (b) ? (a) : (b))
int cmp(const int *a, const int *b)
{
    if(*a > *b) {
        return 1;
    } else if(*a < *b) {
        return -1;
    } else {
        return 0;
    }
}
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* intersect(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){
    if(nums1Size == 0 || nums2Size == 0 || nums1 == NULL || nums2 == NULL) {
        *returnSize = 0;
        return NULL;
    }
    
    int* res = (int*)malloc(sizeof(int) * MAX(nums1Size, nums2Size));
    qsort(nums1, nums1Size, sizeof(int), cmp);
    qsort(nums2, nums2Size, sizeof(int), cmp);
    
    int left1 = 0;
    int left2 = 0;
    *returnSize = 0;
    while(left1 < nums1Size && left2 < nums2Size) {
        if(nums1[left1] == nums2[left2]) {
            res[(*returnSize)++] = nums1[left1];
            left1++;
            left2++;
        } else if(nums1[left1] < nums2[left2]) {
            left1++;
        } else {
            left2++;
        }
    }
    
    return res;
}


/*
922. 按奇偶排序数组 II
给定一个非负整数数组 A, A 中一半整数是奇数,一半整数是偶数。

对数组进行排序,以便当 A[i] 为奇数时,i 也是奇数;当 A[i] 为偶数时, i 也是偶数。

你可以返回任何满足上述条件的数组作为答案。

 
示例:

输入:[4,2,5,7]
输出:[4,5,2,7]
解释:[4,7,2,5],[2,5,4,7],[2,7,4,5] 也会被接受。
*/
void swap(int *a, int *b) {
    int tmp;
    tmp = *a;
    *a = *b;
    *b = tmp;
}
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* sortArrayByParityII(int* A, int ASize, int* returnSize){
    if(ASize == 0 || A == NULL) {
        *returnSize = 0;
        return NULL;
    }
    
    int p1 = 0;
    int p2 = 1;
    while(p1 < ASize && p2 < ASize) {
        while(p1 < ASize && A[p1] % 2 == 0) {
            p1 += 2;
        }
        while(p2 < ASize && A[p2] % 2 == 1) {
            p2 += 2;
        }
        if(p1 < ASize && p2 < ASize)
        {
            swap(&A[p1], &A[p2]);
            p1 += 2;
            p2 += 2;
        }
    }
    *returnSize = ASize;
    return A;
}


/*
976. 三角形的最大周长
给定由一些正数(代表长度)组成的数组 A,返回由其中三个长度组成的、面积不为零的三角形的最大周长。

如果不能形成任何面积不为零的三角形,返回 0。
示例 1:

输入:[2,1,2]
输出:5
示例 2:

输入:[1,2,1]
输出:0
示例 3:

输入:[3,2,3,4]
输出:10
示例 4:

输入:[3,6,2,3]
输出:8
*/
int cmp(const int *a, const int *b)
{
    if(*a > *b) {
        return -1;
    } else if(*a < *b) {
        return 1;
    } else {
        return 0;
    }
}

int largestPerimeter(int* A, int ASize){
    if(ASize == 0 || A == NULL) {
        return 0;
    }
    
    qsort(A, ASize, sizeof(int), cmp);
    for(int i = 0; i < ASize - 2; i++) {
        if(A[i + 1] + A[i + 2] > A[i]) {
            return A[i] + A[i + 1] + A[i + 2];
        }
    }
    return 0;
}


/*
1030. 距离顺序排列矩阵单元格
给出 R 行 C 列的矩阵,其中的单元格的整数坐标为 (r, c),满足 0 <= r < R 且 0 <= c < C。

另外,我们在该矩阵中给出了一个坐标为 (r0, c0) 的单元格。

返回矩阵中的所有单元格的坐标,并按到 (r0, c0) 的距离从最小到最大的顺序排,其中,两单元格(r1, c1) 和 (r2, c2) 之间的距离是曼哈顿距离,|r1 - r2| + |c1 - c2|。(你可以按任何满足此条件的顺序返回答案。)

示例 1:

输入:R = 1, C = 2, r0 = 0, c0 = 0
输出:[[0,0],[0,1]]
解释:从 (r0, c0) 到其他单元格的距离为:[0,1]
示例 2:

输入:R = 2, C = 2, r0 = 0, c0 = 1
输出:[[0,1],[0,0],[1,1],[1,0]]
解释:从 (r0, c0) 到其他单元格的距离为:[0,1,1,2]
[[0,1],[1,1],[0,0],[1,0]] 也会被视作正确答案。
示例 3:

输入:R = 2, C = 3, r0 = 1, c0 = 2
输出:[[1,2],[0,2],[1,1],[0,1],[1,0],[0,0]]
解释:从 (r0, c0) 到其他单元格的距离为:[0,1,1,2,2,3]
其他满足题目要求的答案也会被视为正确,例如 [[1,2],[1,1],[0,2],[1,0],[0,1],[0,0]]。
*/
//执行用时击败 92%, 内存消耗击败 100%
int cmp(const int **a, const int **b)
{
    return (*(*a + 2)) - (*(*b + 2));
}
/**
 * Return an array of arrays of size *returnSize.
 * The sizes of the arrays are returned as *returnColumnSizes array.
 * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
 */
int** allCellsDistOrder(int R, int C, int r0, int c0, int* returnSize, int** returnColumnSizes){
    int size = R * C;    
    int** res = (int**)malloc(sizeof(int*) * size);
    for(int i = 0; i < size; i++) {
        res[i] = (int*)malloc(sizeof(int) * 3);
        memset(res[i], 0, sizeof(int) * 3);
        res[i][0] = i / C;
        res[i][1] = i % C;
        res[i][2] = abs(res[i][0] - r0) + abs(res[i][1] - c0);
    }
    
    qsort(res, size, sizeof(int*), cmp);
    //for(int i = 0; i < size; i++) {
    //    printf("%d-%d-%d\n", res[i][0], res[i][1], res[i][2]);
    //}
    
    int *columnSize = (int*)malloc(sizeof(int) * size);
    //memset(columnSize, 2, sizeof(int) * size);
    for(int i = 0; i < size; i++) {
        columnSize[i] = 2;
    }
    
    *returnSize = size;
    *returnColumnSizes = columnSize;
    
    return res;
}


/*
1122. 数组的相对排序
给你两个数组,arr1 和 arr2,

arr2 中的元素各不相同
arr2 中的每个元素都出现在 arr1 中
对 arr1 中的元素进行排序,使 arr1 中项的相对顺序和 arr2 中的相对顺序相同。未在 arr2 中出现过的元素需要按照升序放在 arr1 的末尾。

 
示例:

输入:arr1 = [2,3,1,3,2,4,6,7,9,2,19], arr2 = [2,1,4,3,9,6]
输出:[2,2,2,1,4,3,3,9,6,7,19]
 

提示:

arr1.length, arr2.length <= 1000
0 <= arr1[i], arr2[i] <= 1000
arr2 中的元素 arr2[i] 各不相同
arr2 中的每个元素 arr2[i] 都出现在 arr1 中
*/
int cmp(const int *a, const int *b)
{
    return *a - *b;
}
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* relativeSortArray(int* arr1, int arr1Size, int* arr2, int arr2Size, int* returnSize){
    int data1[1001] = {0}; //计数排序
    int data2[1001] = {0}; //快排
    int data2Size = 0;
    for(int i = 0; i < arr2Size; i++) {
        data1[arr2[i]]++;
    }
    for(int i = 0; i < arr1Size; i++) {
        if(data1[arr1[i]]) {
            data1[arr1[i]]++;
        } else {
            data2[data2Size++] = arr1[i];
        }
    }
    
    int data1Size = 0;
    int* res = (int*)malloc(sizeof(int) * arr1Size);
    for(int i = 0; i < arr2Size; i++) {
        while(data1[arr2[i]] > 1) {
            res[data1Size++] = arr2[i];
            data1[arr2[i]]--;
        }
    }
    
    qsort(data2, data2Size, sizeof(int), cmp);
    memcpy(&res[data1Size], &data2, sizeof(int) * data2Size);
    for(int i = 0; i < arr1Size; i++) {
        printf("%d ", res[i]);
    }
    
    *returnSize = data1Size + data2Size;
    return res;
}


/*
56. 合并区间
给出一个区间的集合,请合并所有重叠的区间。

示例 1:

输入: [[1,3],[2,6],[8,10],[15,18]]
输出: [[1,6],[8,10],[15,18]]
解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
示例 2:

输入: [[1,4],[4,5]]
输出: [[1,5]]
解释: 区间 [1,4] 和 [4,5] 可被视为重叠区间。
*/
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
int cmp(const int **a, const int **b)
{
    return *(*a + 0) - *(*b + 0);
}

/**
 * Return an array of arrays of size *returnSize.
 * The sizes of the arrays are returned as *returnColumnSizes array.
 * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
 */
// 多包含区间从后排序,少包含区间从前排序
int** merge(int** intervals, int intervalsSize, int* intervalsColSize, int* returnSize, int** returnColumnSizes){
    if(intervalsSize == 0) {
        *returnSize = 0;
        return NULL;
    }
    
    qsort(intervals, intervalsSize, sizeof(int*), cmp);
    //for(int i = 0; i < intervalsSize; i++) {
    //    printf("%d,%d\n", intervals[i][0], intervals[i][1]);
    //}
    
    int resSize = 0;
    int** res = (int**)malloc(sizeof(int*) * intervalsSize);
    for(int i = 0; i < intervalsSize; i++) {
        res[i] = (int*)malloc(sizeof(int) * 2);
    }    
    
    for(int i = 0; i < intervalsSize; i++) {
        if(i + 1 < intervalsSize && intervals[i][1] >= intervals[i + 1][0]) {
            intervals[i + 1][0] = MIN(intervals[i][0], intervals[i + 1][0]);
            intervals[i + 1][1] = MAX(intervals[i][1], intervals[i + 1][1]);
        } else {
            res[resSize][0] = intervals[i][0];
            res[resSize][1] = intervals[i][1];
            resSize++;
        }
    }
    
    *returnSize = resSize;
    int* resCol = (int*)malloc(sizeof(int) * resSize);
    for(int i = 0; i < resSize; i++) {
        resCol[i] = 2;
    }
    *returnColumnSizes = resCol;
    
    return res;
}

/*
147. 对链表进行插入排序
插入排序算法:

插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。
每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。
重复直到所有输入数据插入完为止。
 

示例 1:

输入: 4->2->1->3
输出: 1->2->3->4
示例 2:

输入: -1->5->3->4->0
输出: -1->0->3->4->5
*/
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
typedef struct ListNode* ListLink;
struct ListNode* insertionSortList(struct ListNode* head){
    if(head == NULL || head->next == NULL) {
        return head;
    }
    
    ListLink pre;
    ListLink headBack = (ListLink)malloc(sizeof(struct ListNode));
    headBack->next = head;
    while(head != NULL && head->next != NULL) {
        if(head->val <= head->next->val) {
            head = head->next;
            continue;
        }
        
        pre = headBack;
        while(head->next->val > pre->next->val) {
            pre = pre->next;
        }
        
        ListLink cur = head->next;
        head->next = cur->next;
        cur->next = pre->next;
        pre->next = cur;
    }
    return headBack->next;
}

 

你可能感兴趣的:(OJ)