Algorithm problems in C

Sort in order of 代码随想录

Array

  1. Binary Search
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int search(int* nums, int numsSize, int target) {
int a = 0, b = numsSize - 1, mid;

while(a <= b) {
mid = (a + b) / 2; // the middle or left one
if (target > nums[mid]) {
a = mid + 1;
}
else if (target < nums[mid]) {
b = mid - 1;
}
else return mid;
}
return -1;
}
  1. Remove Element
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int removeElement(int* nums, int numsSize, int val) {
int* a = nums;
int* b = nums;
int i, len = numsSize;
for (i = 0; i < numsSize; i++) {
if(*b != val) {
*a = *b;
a++;
}
else len--;
b++;

}
return len;
}
  1. Squares of a Sorted Array
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int* sortedSquares(int* nums, int numsSize, int* returnSize) {
int* newArr = malloc(numsSize * sizeof(int)); // Allocate memory for the new array

int left = 0; // Pointer to the start of the array
int right = numsSize - 1; // Pointer to the end of the array

// Loop from the end of the newArr towards the beginning
for (int i = numsSize - 1; i >= 0; i--) {
int litem = nums[left];
int ritem = nums[right];
if (litem * litem > ritem * ritem) {
newArr[i] = litem * litem;
left++; // Move left pointer to the right
} else {
newArr[i] = ritem * ritem;
right--; // Move right pointer to the left
}
}

*returnSize = numsSize; // Update the return size
return newArr;
}
  1. Minimum Size Subarray Sum

Out of limited time

1
2
3
4
5
6
7
8
9
10
11
12
13
int minSubArrayLen(int target, int* nums, int numsSize) {
int min = 1000000;
int i, j;
for (i = 0; i < numsSize; i++) {
int sum = nums[i];
j = i + 1;
while (sum < target && j < numsSize) {
sum += nums[j++];
}
if (min > j - i && sum >= target) min = j - i;
}
return min == 1000000 ? 0 : min;
}

Modified edition, using double pointer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int minSubArrayLen(int target, int* nums, int numsSize) {
if (numsSize == 1) return *nums >= target;

int* a = nums; // double the pointers
int* b = nums; // point to the latter one
int sum = *nums; // sum the nums between a and b
int len = 1; // the size of the sub-array
int min = 1000000; // initialize the min
int i = 1; // counter, avoid overflowing

while (i < numsSize) {
while (sum < target && i < numsSize) {
sum += *(++b);
len++;
i++;
}
while (sum >= target){
if (min > len) min = len;
sum -= *(a++);
len--;
}
}
return min != 1000000 ? min : 0;
}
  1. Spiral Matrix II
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
* 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** generateMatrix(int n, int* returnSize, int** returnColumnSizes) {
*returnSize = n;
*returnColumnSizes = (int*)malloc(n * sizeof(int));
int** matrix = (int**)malloc(n * sizeof(int*));

for (int i = 0; i < n; i++) {
matrix[i] = (int*)malloc(n * sizeof(int));
(*returnColumnSizes)[i] = n;
}

int turns = n / 2;
int col = 0, row = 0;
int num = 0;
for (int i = 0; i < turns; i++) {
for (; col < n - 1 - i; col++) matrix[row][col] = ++num; // left -> right
for (; row < n - 1 - i; row++) matrix[row][col] = ++num; // up -> down
for (; col > i; col--) matrix[row][col] = ++num; // right -> left
for (; row > i; row--) matrix[row][col] = ++num; // down -> up
row++;
col++;
}
if (n % 2 == 1) matrix[row][col] = n * n;

return matrix;
}
  1. Remove Linked List Elements
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
struct ListNode* removeElements(struct ListNode* head, int val) {
while (head != NULL && head->val == val) {
head = head->next;
}
if (!head) return head;
struct ListNode* pre = head;
struct ListNode* p = head->next;

while(p != NULL) {
if (p->val == val) {
pre->next = p->next;
free(p);
p = pre->next;
}
else {
pre = p;
p = p->next;
}
}
return head;
}
  1. Design Linked List
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
typedef struct MyLinkedList {
int val;
struct MyLinkedList *prev, *next;
} MyLinkedList;


MyLinkedList* myLinkedListCreate() {
MyLinkedList* head = (MyLinkedList*)malloc(sizeof(MyLinkedList));
if (head == NULL) return -1;
head->val = 0;
head->prev = NULL;
head->next = NULL;
return head;
}

int myLinkedListGet(MyLinkedList* obj, int index) {
MyLinkedList* p = obj->next;
int i = 0;

for (; i < index && p != NULL; i++) p = p->next;

if (i == index && p != NULL) return p->val;
else return -1;
}

void myLinkedListAddAtHead(MyLinkedList* obj, int val) {
MyLinkedList* p = (MyLinkedList*)malloc(sizeof(MyLinkedList));
p->val = val;

MyLinkedList* firstNode = obj->next;

obj->next = p;
p->prev = NULL;

p->next = firstNode;
if (firstNode != NULL) firstNode->prev = p;
}

void myLinkedListAddAtTail(MyLinkedList* obj, int val) {
MyLinkedList* p = (MyLinkedList*)malloc(sizeof(MyLinkedList));
if (obj == NULL || p == NULL) return ;
p->val = val;
p->next = NULL;

MyLinkedList* tailNode = obj;

while (tailNode->next != NULL) tailNode = tailNode->next;

tailNode->next = p;
p->prev = tailNode;
}

void myLinkedListAddAtIndex(MyLinkedList* obj, int index, int val) {
MyLinkedList* p = (MyLinkedList*)malloc(sizeof(MyLinkedList));
p->val = val;

MyLinkedList* pre = obj;
MyLinkedList* sub = obj->next;
int i;
for (i = 0; i < index && sub != NULL; i++) {
pre = sub;
sub = sub->next;
}

if (i != index) return ;
pre->next = p;
if (pre != obj) p->prev = pre;
p->next = sub;
if (sub != NULL) sub->prev = p;
}

void myLinkedListDeleteAtIndex(MyLinkedList* obj, int index) {
MyLinkedList* p = obj;
for (int i = 0; i < index && p != NULL; i++) p = p->next;

if (p != NULL && p->next != NULL) {
MyLinkedList* toDel = p->next;
if (toDel->next != NULL) toDel->next->prev = p;
p->next = toDel->next;
free(toDel);
}
}

void myLinkedListFree(MyLinkedList* obj) {
free(obj);
}

/**
* Your MyLinkedList struct will be instantiated and called as such:
* MyLinkedList* obj = myLinkedListCreate();
* int param_1 = myLinkedListGet(obj, index);

* myLinkedListAddAtHead(obj, val);

* myLinkedListAddAtTail(obj, val);

* myLinkedListAddAtIndex(obj, index, val);

* myLinkedListDeleteAtIndex(obj, index);

* myLinkedListFree(obj);
*/
  1. Reverse Linked List
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseList(struct ListNode* head) {
struct ListNode* pre = NULL;
struct ListNode* sub = head;

while (sub != NULL) {
struct ListNode* tmp = sub->next;
sub->next = pre;
pre = sub;
sub = tmp;
}

head = pre;
return head;
}
  1. Swap Nodes in Pairs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* swapPairs(struct ListNode* head) {
if (head == NULL || head->next == NULL) return head;
// Divide into several parts, each part has "pre"(the node points to this part) and "sub"(a node succeed from this part)
struct ListNode* pre = NULL;
struct ListNode* a = head;
struct ListNode* b = a->next;
head = b;

while(b != NULL) {
struct ListNode* sub = b->next;
if (pre != NULL) pre->next = b;
b->next = a;
a->next = sub;

pre = a;
a = sub;
if (a != NULL) b = a->next;
else b = NULL;
}

return head;
}
  1. Remove Nth Node From End of List
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
struct ListNode* preNode = head; // the node before the delNode
struct ListNode* endNode = head;

for (int i = 0; i < n && endNode != NULL; i++) endNode = endNode->next;
if (endNode == NULL) return head->next; // delete the first node

while (endNode->next != NULL) {
preNode = preNode->next;
endNode = endNode->next;
}

struct ListNode* delNode = preNode->next;
preNode->next = delNode->next;
free(delNode);
return head;
}
  1. Intersection of Two Linked Lists LCCI
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
if (headA == NULL || headB == NULL) return NULL;
struct ListNode *ptr1 = headA;
struct ListNode *ptr2 = headB;

int flag = 0; // ensure the rest of nodes are the same
struct ListNode *res;
while (ptr1 != NULL || ptr2 != NULL) {
if (ptr1 == NULL && ptr2 != NULL) ptr1 = headB;
if (ptr1 != NULL && ptr2 == NULL) ptr2 = headA;

if (ptr1 == ptr2) { // check the 2 nodes whether the same node, instead of checking the values
if (flag != 1) res = ptr1;
flag = 1;
}
else flag = 0;
ptr1 = ptr1->next;
ptr2 = ptr2->next;
}
if (flag == 1) return res;
else return NULL;
}
  1. Linked List Cycle II
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode *slow = head;
struct ListNode *fast = head;

while (fast != NULL && fast->next != NULL) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) { // when the 2 nodes meet each other, there are some mathematic problems
struct ListNode *index1 = head;
struct ListNode *index2 = fast;
while (index1 != index2) {
index1 = index1->next;
index2 = index2->next;
}
return index1;
}
}
return NULL;
}

Hash Table

  1. Valid Anagram
1
2
3
4
5
6
7
8
9
10
11
12
13
14
bool isAnagram(char* s, char* t) {
int record[26] = {0};
int lenA = strlen(s), lenB = strlen(t);
if (lenA != lenB) return false;
for (int i = 0; i < lenA; i++) // traverse all the characters
record[s[i] - 'a'] += 1;
for (int i = 0; i < lenB; i++)
record[t[i] - 'a'] -= 1;

for (int j = 0; j < 26; i++) // traverse all the records
if (record[i] != 0) return false;

return true;
}
  1. Intersection of Two Arrays
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* intersection(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize) {
int record1[1001] = {0}, record2[1001] = {0}; // record the number of occurences
int* ans = malloc(1001 * sizeof(int)); // store the result
*returnSize = 0;
for (int i = 0; i < nums1Size; i++) record1[nums1[i]]++;
for (int i = 0; i < nums2Size; i++) record2[nums2[i]]++;

for (int i = 0; i < 1001; i++)
if (record1[i] != 0 && record2[i] != 0) ans[(*returnSize)++] = i;

ans = realloc(ans, (*returnSize) * sizeof(int));
return ans;
}
  1. Happy Number
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int get_next(int number) {
int sum = 0;
while (number > 0) {
sum += (number % 10) * (number % 10); // square the number in each bit
number /= 10;
}
return sum;
}

bool isHappy(int n) {
/*
* Floyd's cycle detection algorithm (also known
* as the tortoise and the hare algorithm)
*/
int slow = get_eachBitSquare(n), fast = get_eachBitSquare(get_eachBitSquare(n));
while (slow != fast && fast != 1) {
slow = get_eachBitSquare(slow);
fast = get_eachBitSquare(get_eachBitSquare(fast));
}
return fast == 1;
}
  1. Two Sum
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* twoSum(int* nums, int numsSize, int target, int* returnSize) {
int* ans = malloc(2 * sizeof(int));
for (int i = 0; i < numsSize; i++) {
for (int j = i + 1; j < numsSize; j++)
if (nums[i] + nums[j] == target) {
ans[0] = i;
ans[1] = j;
*returnSize = 2;
return ans;
}
}
return ans;
}
  1. 4Sum II
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
struct hashTable {
int key;
int val;
UT_hash_handle hh;
};

int fourSumCount(int* nums1, int nums1Size, int* nums2, int nums2Size, int* nums3, int nums3Size, int* nums4, int nums4Size){
struct hashTable* hashtable = NULL;
for (int i = 0; i < nums1Size; i++) {
for (int j = 0; j < nums2Size; j++) {
int ikey = nums1[i] + nums2[j];
struct hashTable* tmp;
HASH_FIND_INT(hashtable, &ikey, tmp);
if (tmp == NULL) {
tmp = malloc(sizeof(struct hashTable));
tmp->key = ikey;
tmp->val = 1;
HASH_ADD_INT(hashtable, key, tmp);
}
else {
tmp->val++;
}
}
}

int ans = 0;
for (int k = 0; k < nums3Size; k++) {
for (int l = 0; l < nums4Size; l++) {
int ikey = -nums3[k] - nums4[l];
struct hashTable* tmp;
HASH_FIND_INT(hashtable, &ikey, tmp);
if (tmp != NULL) {
ans += tmp->val;
}
}
}
free(hashtable);
return ans;
}
  1. Ransom Note
  • Method One(Hash Table)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
struct hashTable {
char key;
int val;
UT_hash_handle hh;
};

bool canConstruct(char* ransomNote, char* magazine) {
struct hashTable* hashtable = NULL;
int lenMag = strlen(magazine), lenRan = strlen(ransomNote);
for (int i = 0; i < lenMag; i++) {
char ckey = magazine[i];
struct hashTable* tmp;
HASH_FIND(hh, hashtable, &ckey, sizeof(char), tmp);
if (tmp == NULL) {
tmp = malloc(sizeof(struct hashTable));
tmp->key = ckey; tmp->val = 1;
HASH_ADD(hh, hashtable, key, sizeof(char), tmp);
}
else tmp->val++;
}

for (int i = 0; i < lenRan; i++) {
char ckey = ransomNote[i];
struct hashTable* tmp;
HASH_FIND(hh, hashtable, &ckey, sizeof(char), tmp);
if (tmp == NULL || tmp->val == 0) return false;
else tmp->val--;
}
return true;
}
  • Method Two(Array)
1
2
3
4
5
6
7
8
9
10
11
bool canConstruct(char* ransomNote, char* magazine) {
int record[26] = {0};
int lenA = strlen(magazine), lenB = strlen(ransomNote);
for (int i = 0; i < lenA; i++) record[magazine[i] - 'a']++;
for (int i = 0; i < lenB; i++) {
if (record[ransomNote[i] - 'a'] == 0) return false;
record[ransomNote[i] - 'a']--;
}

return true;
}
  1. 3Sum
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/**
* 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 Partition(int* nums, int low, int high) {
int pivot = nums[low];
while (low < high) {
while (low < high && pivot <= nums[high]) --high;
nums[low] = nums[high];
while (low < high && pivot >= nums[low]) low++;
nums[high] = nums[low];
}
nums[low] = pivot;
return low;
}

void QuickSort(int* nums, int low, int high) {
if (low < high) {
int pos = Partition(nums, low, high);
QuickSort(nums, low, pos - 1);
QuickSort(nums, pos + 1, high);
}
}

int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes) {
QuickSort(nums, 0, numsSize - 1);
int** ans = malloc(3000 * sizeof(int*));
int cnt = 0;
for (int i = 0; i < numsSize - 2; i++) {
if (i > 0 && nums[i] == nums[i - 1]) continue;
int left = i + 1, right = numsSize - 1;
while (left < right) {
int sum = nums[i] + nums[left] + nums[right];
if (sum > 0) --right;
else if (sum < 0) left++;
else {
ans[cnt] = malloc(3 * sizeof(int));
ans[cnt][0] = nums[i];
ans[cnt][1] = nums[left];
ans[cnt][2] = nums[right];
cnt++;
while (left < right && nums[left] == nums[left + 1]) left++;
while (left < right && nums[right] == nums[right - 1]) --right;
left++;
right--;
}
}
}
*returnSize = cnt;
*returnColumnSizes = malloc(cnt * sizeof(int));
for (int i = 0; i < cnt; i++) (*returnColumnSizes)[i] = 3;
ans = realloc(ans, cnt * sizeof(int*));
return ans;
}
  1. 4Sum
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/**
* 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 Partition(int* nums, int low, int high) {
int pivot = nums[low];
while (low < high) {
while (low < high && pivot <= nums[high]) --high;
nums[low] = nums[high];
while (low < high && pivot >= nums[low]) low++;
nums[high] = nums[low];
}
nums[low] = pivot;
return low;
}

void QuickSort(int* nums, int low, int high) {
if (low < high) {
int pivotpos = Partition(nums, low, high);
QuickSort(nums, low, pivotpos - 1);
QuickSort(nums, pivotpos + 1, high);
}
}


int** fourSum(int* nums, int numsSize, int target, int* returnSize, int** returnColumnSizes) {
int** ans = malloc(200 * sizeof(int*));
int cnt = 0;
QuickSort(nums, 0, numsSize - 1);
for (int i = 0; i < numsSize; i++) {
if (i > 0 && nums[i] == nums[i - 1]) continue;
for (int j = i + 1; j < numsSize; j++) {
if (j > i + 1 && nums[j] == nums[j - 1]) continue;
int left = j + 1, right = numsSize - 1;
while (left < right) {
// Use "long long" type to avoid overflowing, as nums[i] <= 10^9.
long long sum = (long long) nums[i] + nums[j] + nums[left] + nums[right];
if (sum > target) --right;
else if (sum < target) left++;
else {
ans[cnt] = malloc(4 * sizeof(int));
ans[cnt][0] = nums[i];
ans[cnt][1] = nums[j];
ans[cnt][2] = nums[left];
ans[cnt][3] = nums[right];
cnt++;
while (left < right && nums[left] == nums[left + 1]) left++;
while (left < right && nums[right] == nums[right - 1]) --right;
left++;
--right;
}
}
}
}
*returnSize = cnt;
*returnColumnSizes = malloc(cnt * sizeof(int));
for (int i = 0; i < cnt; i++) (*returnColumnSizes)[i] = 4;
ans = realloc(ans, cnt * sizeof(int*));
return ans;
}

String

  1. Reverse String
1
2
3
4
5
6
7
void reverseString(char* s, int sSize) {
for (int low = 0, high = sSize - 1; low < high; low++, --high) {
char tmp = s[low];
s[low] = s[high];
s[high] = tmp;
}
}
  1. Reverse String II
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void swap(char* s, int low, int high) {
for (; low < high; low++, high--) {
char tmp = s[low];
s[low] = s[high];
s[high] = tmp;
}
}

char* reverseStr(char* s, int k) {
int len = strlen(s), i = 0;
while (1) {
i += 2 * k;
if (i < len) swap(s, i - 2 * k, i - k - 1);
else if (i == len || i - len < k) {
swap(s, i - 2 * k, i - k - 1);
break;
}
else {
// change the latter one to "len - 1", as "i - k - 1" will overflow.
swap(s, i - 2 * k, len - 1);
break;
}
}
return s;
}
  1. Replace Number
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

char* replaceNum(char* s) {
int len = strlen(s), cnt = 0;
char t[] = "number";
char* str = malloc(60000 * sizeof(char));

for (int i = 0; i < len; i++) {
char c = s[i];
if (c >= '0' && c <= '9')
for (int j = 0; j < 6; j++) str[cnt++] = t[j];
else {
str[cnt] = c;
cnt++;
}
}
str[cnt++] = '\0';
str = realloc(str, cnt * sizeof(char));
return str;
}

int main() {
char s[10000];
scanf("%s", s);
char* ans = replaceNum(s);
printf("%s", ans);
return 0;
}
  1. Reverse Words in a String
1