常用排序、搜索算法(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;
}