leetcodo--Easy part
char* addBinary(char* a, char* b) { if (*a == '\0') return b; if (*b == '\0') return a; int index_a = strlen(a) - 1; int index_b = strlen(b) - 1; int carry = 0; int sum = 0; int index_ans = 0; char *ans = NULL; if (index_a >= index_b) ans = malloc(sizeof(char) * (index_a + 1 + 2)); //strlen(a) + 2, carry-bit and '\0' else ans = malloc(sizeof(char) * (index_b + 1 + 2)); while (index_a >= 0 && index_b >= 0) { sum = (a[index_a] - '0') + (b[index_b] - '0') + carry; carry = sum/2; sum %= 2; ans[index_ans++] = sum + '0'; --index_a; --index_b; } while (index_a >= 0) { sum = a[index_a] - '0' + carry; carry = sum / 2; sum %= 2; ans[index_ans++] = sum + '0'; --index_a; } while (index_b >= 0) { sum = b[index_b] - '0' + carry; carry = sum / 2; sum %= 2; ans[index_ans++] = sum + '0'; --index_b; } if (carry > 0) { ans[index_ans++] = carry + '0'; } ans[index_ans] = '\0'; return ans; }
写得和add binary差不多,又臭又长
然后发现可以这么写
1 char* addBinary(char* a, char* b) { 2 if (*a == '\0') return b; 3 if (*b == '\0') return a; 4 5 int len_a = strlen(a), len_b = strlen(b); 6 char c = 0; 7 int len_ans; 8 char *ans = NULL; 9 10 len_ans = 2 + ((len_a > len_b) ? len_a : len_b); 11 ans = malloc(sizeof(char) * len_ans); 12 memset(ans, '0', sizeof(char) * len_ans); 13 ans[--len_ans] = '\0'; 14 while (len_ans--) { 15 c += ((len_a > 0) ? (a[--len_a] - '0') : 0) + ((len_b > 0) ? (b[--len_b] - '0') : 0); 16 17 ans[len_ans] = c % 2 + '0'; 18 c /= 2; 19 } 20 if (ans[0] == '0') ans++; 21 return ans; 22 }
Climbing stairs
动态规划,爬到台阶n设为一个状态,state(n) 表示这个状态下有多少种爬法,如果一步只能走1或2阶楼梯,那么
现在的状态的前一个状态有两种可能,state(n-1)和state(n-2),故有state(n) = state(n-1) + state(n-2)。
初始状态:state(1) = 1, state(2) = 2;
int climbStairs(int n) { //n2 means n int n2 = 1; int n1 = 2; int temp; if (n == 1) return n2; if (n == 2) return n1; for (int i = 3; i <= n; i++) { temp = n1 + n2; n2 = n1; n1 = temp; } return n1; }
88.Merge Sorted Array
已知范围可以从后边开始。。
void merge(int* nums1, int m, int* nums2, int n) { int i1 = m - 1; int i2 = n -1; while (i1 >= 0 && i2 >= 0) { if (nums1[i1] > nums2[i2]) { nums1[i1+i2+1] = nums1[i1]; i1--; } else{ nums1[i1+i2+1] = nums2[i2]; i2--; } } while(i2 >= 0) { nums1[i1+i2+1] = nums2[i2]; i2--; } }
338.Counting Bits
本来想的是 any i in [0,num] 的解法,后来发现都已经用一个数组保存子问题了。。。也是一种DP吧
23ms
1 int* countBits(int num, int* returnSize) { 2 num++; 3 *returnSize = num; 4 int *bitCountArray = malloc(sizeof(int) * (*returnSize)); 5 bitCountArray[0] = 0; 6 for (int i = 1; i < num; i++) { 7 bitCountArray[i] = i&1 ? (bitCountArray[i>>1] + 1) : bitCountArray[i>>1]; 8 } 9 return bitCountArray; 10 }
原来的解法
1 int* countBits(int num, int* returnSize) { 2 num++; 3 *returnSize = num; 4 int *bitCountArray = malloc(sizeof(int) * (*returnSize)); 5 bitCountArray[0] = 0; 6 for (int i = 1; i < num; i++) { 7 bitCountArray[i] = pop(i); 8 } 9 return bitCountArray; 10 } 11 inline int pop(unsigned x) { 12 x = (x & 0x55555555) + ((x >> 1) & 0x55555555); 13 x = (x & 0x33333333) + ((x >> 2) & 0x33333333); 14 x = (x & 0x0f0f0f0f) + ((x >> 4) & 0x0f0f0f0f); 15 x = (x & 0x00ff00ff) + ((x >> 8) & 0x00ff00ff); 16 x = (x & 0x0000ffff) + ((x >> 16) & 0x0000ffff); 17 return x; 18 }
Best time to Buy and Sell
买卖石头是有顺序的,最简单的方法超时:
1 int maxProfit(int* prices, int pricesSize) { 2 int max_diff = 0; 3 for (int i = 0; i < pricesSize; i++) { 4 int diff = find_diff(i, pricesSize, prices); 5 if (diff > max_diff) 6 max_diff = diff; 7 } 8 return max_diff; 9 } 10 11 int find_diff(int low, int high, int *prices) { 12 int max = prices[low]; 13 for (int i = low; i < high; i++) { 14 if (prices[i] > max) 15 max = prices[i]; 16 } 17 return max-prices[low]; 18 }
可以换一个思路,虽然只能买卖一次,但是可以通过连续买卖模拟出最佳操作,因为profile = buy:day[i] + sell:day[i+1] = day[i+1] - day[i],
故如果在第k天存在最佳卖出的价格,其间存在关系 ((i+1) - i) + ((i+2) - (i+1)) +...+(k - (k-1)) = k - i ,
整个过程不用回退。(一句话解释:今天买明天卖,明天卖的可以在明天接着买回来)
所以可以写成一个online的算法(中途结束会给出近似解,有点像另一道最长子序的题)
1 int maxProfit(int price[], int n) 2 { 3 int ret = 0, past = 0; 4 for(int i = 1; i < n; i++) 5 { 6 ret += price[i] - price[i-1]; 7 if(ret < 0) ret = 0; 8 if(ret > past) past = ret; 9 } 10 return past; 11 }
1. Two Sum
用hash
1 typedef struct linkList{ 2 int data; 3 int index_nums; 4 struct linkList *ptr; 5 }linkList; 6 7 void hashInsert(int index, int val, int hashSize, linkList *hashT){ //这是一个链表实现的哈希表,参数int i保存hash节点在原来数组中下标 8 int tmp_val; 9 tmp_val = (val < 0)? -val : val; 10 linkList *tmp_ptr = &hashT[tmp_val % hashSize]; 11 while(tmp_ptr->ptr) tmp_ptr = tmp_ptr->ptr; 12 tmp_ptr->ptr = (linkList *)calloc(1, sizeof(linkList)); 13 tmp_ptr->ptr->data = val; 14 tmp_ptr->ptr->index_nums = index; 15 } 16 17 _Bool hashSearch(int exist_index, int val, int *return_index, int hashSize, linkList *hashT){ 18 int tmp_val; 19 (val < 0) ? (tmp_val = (-1) * val) : (tmp_val = val); 20 linkList *tmp_ptr = &hashT[tmp_val % hashSize]; 21 tmp_ptr = tmp_ptr->ptr; 22 while(tmp_ptr) { 23 if((tmp_ptr->data == val) && (tmp_ptr->index_nums != exist_index)){ //这个数不是其 24 *return_index = tmp_ptr->index_nums; 25 return true; 26 } 27 tmp_ptr = tmp_ptr->ptr; 28 } 29 return false; 30 } 31 32 int* twoSum(int* nums, int numsSize, int target) { 33 linkList *hashT; 34 int i, *ans, val, index, hashTSize = numsSize; 35 36 hashT = (linkList *)calloc(hashTSize, sizeof(linkList)); 37 ans = (int *)calloc(2, sizeof(int)); 38 for(i = 0; i < numsSize; i++) hashInsert(i, nums[i], hashTSize, hashT); 39 for(i = 0; i < numsSize; i++) { 40 val = target - nums[i]; 41 if(hashSearch(i, val, &index, hashTSize, hashT)){ 42 ans[0] = i; 43 ans[1] = index; 44 break; 45 } 46 } 47 return ans; 48 }
6. ZigZag Conversion
题目给出的排版不清楚,看文字说明就好
因为读的顺序是 第0行->第1行->...->第nRows-1行,所以可以根据这一点创建一个大小为nRows的二维数组,[[row0],[row1],...,],分别保存每一行的数据。
然后遍历字符串,将每个字符放入它应在的数组,遍历后再把二维数组归为一个数组。
1 char *convert(char *s, int nRows) { 2 if (nRows <= 1 || s == NULL) return s; 3 4 int row = 0; 5 int step = 1; 6 7 char **rows = malloc(nRows * sizeof(char *)); 8 for (int i = 0; i < nRows; i++) { 9 rows[i] = calloc(300, sizeof(char)); 10 } 11 for (int i = 0; i < strlen(s); i++) { 12 if (row == nRows-1) step = -1; 13 if (row == 0) step = 1; 14 strncat(rows[row], s+i, 1); 15 row += step; 16 } 17 18 char *ans = calloc(300 * nRows, sizeof(char)); 19 20 for (int i = 0; i < nRows; i++) { 21 strcat(ans, rows[i]); 22 } 23 24 for (int i = 0; i < nRows; i++) { 25 free(rows[i]); 26 } 27 free(rows); 28 29 return ans; 30 }
还有一种解法就是根据每一行的数的下标关系将其放到对应的位置。
在内部循环中,每次放入两个同一行的数(如果不是第一行或者最后一行,则每次只放入一个数)
1 char* convert(char* s, int numRows) { 2 int n=strlen(s); 3 char* a = malloc(sizeof(char) * (n+1)); 4 int k=0; 5 if(numRows==1 || n<=numRows)return s; 6 for(int i=0;i<numRows;i++) 7 { 8 for(int j=i;j<n;j+=2*(numRows-1)) 9 { 10 a[k++]=s[j]; 11 if(i!=0 && i!=numRows-1) 12 { 13 int t=j+2*(numRows-1)-2*i; 14 if(t<n) 15 a[k++]=s[t]; 16 } 17 } 18 } 19 a[k]='\0'; 20 return a; 21 }
7. Reverse Integer
主要考虑一下乘法溢出,这里用的csapp里的tmul_ok
1 int reverse(int x) { 2 int unit; 3 int reverse_x = 0; 4 int positive_x = x; 5 while(positive_x/10 != 0) 6 { 7 unit = positive_x % 10; 8 reverse_x = reverse_x*10 + unit; 9 positive_x /= 10; 10 } 11 if(!tmul_ok(reverse_x, 10)) 12 return 0; 13 reverse_x = reverse_x*10 + positive_x; 14 15 return reverse_x; 16 } 17 int tmul_ok(int x, int y) 18 { 19 return !x || x*y/x == y; 20 }
8. String to Integer (atoi)
主要考虑加法溢出、乘法溢出
1 int myAtoi(char* str) { 2 int i, n, sign; 3 4 for(i = 0; isspace(str[i]); i++) 5 ; 6 sign = ((str[i] == '-') ? -1 : 1); 7 if(str[i] == '+' || str[i] == '-') 8 i++; 9 for(n = 0; isdigit(str[i]); i++){ 10 if(!tmul_ok(10, n)){ 11 return sign==1 ? 2147483647 : -2147483648; 12 } 13 n = 10 * n; 14 if(!tadd_ok(sign*n, sign*(str[i]-'0'))) 15 return sign==1 ? 2147483647 : 2147483648; 16 n = n + str[i] - '0'; 17 } 18 return sign * n; 19 } 20 int tmul_ok(int x, int y) 21 { 22 return x && x*y/x == y; 23 } 24 int tadd_ok(int x, int y) 25 { 26 int sum = x + y; 27 int neg_over = x < 0 && y < 0 && sum >= 0; 28 int pos_over = x >= 0 && y >= 0 && sum < 0; 29 return !neg_over && !pos_over; 30 }
9. Palindrome Number
1 bool isPalindrome(int x) { 2 if (x < 0) return false; 3 int y=0; 4 int xx=x; 5 while (xx>0) { 6 y = y*10 + xx%10; 7 xx/=10; 8 } 9 return (y == x); 10 }
14. Longest Common Prefix
一个二维数组strs,有strsSize个字符指针
如果每次都完整地比较两个相邻的字符串,那么当遇到不相等的字符时就会跳出,忽略了后面可能更短的部分,比如["abab","aba",""]所以每次必须比较同一个位置上所有字符串的字符。
1 char* longestCommonPrefix(char** strs, int strsSize) { 2 int i,j; 3 char* s=""; 4 if(strsSize==0) return s; 5 for(i = 1; i < strsSize; i++) 6 for (j = 0; j < strlen(*strs); j++) 7 8 if(*(*(strs+i)+j)!=*(*strs+j)) goto EXIT; 9 EXIT: 10 if(j==0) return s; 11 *(*strs+j)='\0'; 12 return *strs; 13 }
19. Remove Nth Node From End of List
可以设置两个节点,倒数第n个也就是其中一个节点比另一个节点“慢”n个节点
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * struct ListNode *next; 6 * }; 7 */ 8 struct ListNode* removeNthFromEnd(struct ListNode* head, int n) { 9 struct ListNode *scout = head, *target = head; 10 int count = 0; 11 while(scout){ 12 scout = scout->next; 13 if(count > n) target = target->next; 14 count++; 15 } 16 if(count > n) target->next = target->next->next; 17 else head = head->next; 18 return head; 19 }
20. Valid Parentheses
经典的括号匹配问题
1 bool isValid(char* s) 2 { 3 char a[10000]; 4 int i, j, k, ct1=0; 5 for(i = 0; i < strlen(s); i++) 6 { 7 switch(s[i]) 8 { 9 case '(': a[ct1]='(';ct1++;break; 10 case '{': a[ct1]='{';ct1++;break; 11 case '[': a[ct1]='[';ct1++;break; 12 case ')': if(a[ct1-1]=='(')ct1--;else return false;break; 13 case '}': if(a[ct1-1]=='{')ct1--;else return false;break; 14 case ']': if(a[ct1-1]=='[')ct1--;else return false;break; 15 } 16 } 17 if(ct1==0) 18 return true; 19 else 20 return false; 21 }
21. Merge Two Sorted Lists
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * struct ListNode *next; 6 * }; 7 */ 8 struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2) { 9 struct ListNode* dummy = malloc(sizeof(struct ListNode)); 10 struct ListNode* ptr = dummy; 11 dummy->next = NULL; 12 if (l1 == NULL) 13 return l2; 14 else if (l2 == NULL) 15 return l1; 16 while (l1 != NULL && l2 != NULL) { 17 if (l1->val > l2->val) { 18 ptr->next = l2; 19 l2 = l2->next; 20 } 21 else { 22 ptr->next = l1; 23 l1 = l1->next; 24 } 25 ptr = ptr->next; 26 } 27 if (l1 == NULL) 28 ptr->next = l2; 29 else if(l2 == NULL) 30 ptr->next = l1; 31 ptr = dummy->next; 32 free(dummy); 33 return ptr; 34 }
24. Swap Nodes in Pairs
基本的链表变换操作
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * struct ListNode *next; 6 * }; 7 */ 8 struct ListNode* swapPairs(struct ListNode* head) { 9 if(head == NULL) 10 return head; 11 if(head->next == NULL) 12 return head; 13 struct ListNode *ptr_pre; 14 struct ListNode *ptr; 15 struct ListNode *ptr_next; 16 struct ListNode *dummy = malloc(sizeof(struct ListNode)); 17 ptr = head; 18 ptr_next = head->next; 19 ptr_pre = dummy; 20 ptr_pre->next = ptr; 21 while(ptr_next){ 22 ptr->next = ptr_next->next; 23 ptr_next->next = ptr; 24 ptr_pre->next = ptr_next; 25 26 ptr_pre = ptr; 27 if(ptr->next) 28 ptr = ptr->next; 29 ptr_next = ptr->next; 30 } 31 head = dummy->next; 32 free(dummy); 33 return head; 34 }
26. Remove Duplicates from Sorted Array
设置一个index指向最后一个未重复的元素
1 int removeDuplicates(int* nums, int numsSize) { 2 if (numsSize == 0) return 0; 3 int i = 0; 4 int j; 5 for (j = 1; j < numsSize; j++) { 6 if (nums[i] != nums[j]) { 7 i++; 8 nums[i] = nums[j]; 9 } 10 } 11 return i+1; 12 }
27. Remove Element
不必真的去除val,因为不能申请额外的空间,只要设置一个普通的index i一直前进,然后再设置一个指向除了val以外的数的index
1 int removeElement(int* nums, int numsSize, int val) { 2 int i = 0; 3 int j = 0; 4 while (i < numsSize) { 5 if (nums[i] == val) { 6 i++; 7 continue; 8 } 9 else { 10 nums[j] = nums[i]; 11 i++; 12 j++; 13 continue; 14 } 15 } 16 return j; 17 }
28. Implement strStr()
暴力搜索,参考K&R的实现
1 int strStr(char *haystack, char *needle) 2 { 3 int i, j, k; 4 if(needle == NULL) return 0; 5 for(i = 0; haystack[i] != '\0'; i++){ 6 for(j = i, k = 0; needle[k] != '\0' && needle[k] == haystack[j]; j++, k++) 7 ; 8 if(k > 0 && needle[k] == '\0') 9 return i; 10 } 11 return -1; 12 }
亦可使用KMP