diff --git a/problems/0005.最长回文子串.md b/problems/0005.最长回文子串.md
index f204a607..99458825 100644
--- a/problems/0005.最长回文子串.md
+++ b/problems/0005.最长回文子串.md
@@ -462,7 +462,92 @@ var longestPalindrome = function(s) {
};
```
+## C
+动态规划:
+```c
+//初始化dp数组,全部初始为false
+bool **initDP(int strLen) {
+ bool **dp = (bool **)malloc(sizeof(bool *) * strLen);
+ int i, j;
+ for(i = 0; i < strLen; ++i) {
+ dp[i] = (bool *)malloc(sizeof(bool) * strLen);
+ for(j = 0; j < strLen; ++j)
+ dp[i][j] = false;
+ }
+ return dp;
+}
+char * longestPalindrome(char * s){
+ //求出字符串长度
+ int strLen = strlen(s);
+ //初始化dp数组,元素初始化为false
+ bool **dp = initDP(strLen);
+ int maxLength = 0, left = 0, right = 0;
+
+ //从下到上,从左到右遍历
+ int i, j;
+ for(i = strLen - 1; i >= 0; --i) {
+ for(j = i; j < strLen; ++j) {
+ //若当前i与j所指字符一样
+ if(s[i] == s[j]) {
+ //若i、j指向相邻字符或同一字符,则为回文字符串
+ if(j - i <= 1)
+ dp[i][j] = true;
+ //若i+1与j-1所指字符串为回文字符串,则i、j所指字符串为回文字符串
+ else if(dp[i + 1][j - 1])
+ dp[i][j] = true;
+ }
+ //若新的字符串的长度大于之前的最大长度,进行更新
+ if(dp[i][j] && j - i + 1 > maxLength) {
+ maxLength = j - i + 1;
+ left = i;
+ right = j;
+ }
+ }
+ }
+ //复制回文字符串,并返回
+ char *ret = (char*)malloc(sizeof(char) * (maxLength + 1));
+ memcpy(ret, s + left, maxLength);
+ ret[maxLength] = 0;
+ return ret;
+}
+```
+
+双指针:
+```c
+int left, maxLength;
+void extend(char *str, int i, int j, int size) {
+ while(i >= 0 && j < size && str[i] == str[j]) {
+ //若当前子字符串长度大于最长的字符串长度,进行更新
+ if(j - i + 1 > maxLength) {
+ maxLength = j - i + 1;
+ left = i;
+ }
+ //左指针左移,右指针右移。扩大搜索范围
+ ++j, --i;
+ }
+}
+
+char * longestPalindrome(char * s){
+ left = right = maxLength = 0;
+ int size = strlen(s);
+
+ int i;
+ for(i = 0; i < size; ++i) {
+ //长度为单数的子字符串
+ extend(s, i, i, size);
+ //长度为双数的子字符串
+ extend(s, i, i + 1, size);
+ }
+
+ //复制子字符串
+ char *subStr = (char *)malloc(sizeof(char) * (maxLength + 1));
+ memcpy(subStr, s + left, maxLength);
+ subStr[maxLength] = 0;
+
+ return subStr;
+}
+```
-----------------------
diff --git a/problems/0052.N皇后II.md b/problems/0052.N皇后II.md
index 78531798..67e439ca 100644
--- a/problems/0052.N皇后II.md
+++ b/problems/0052.N皇后II.md
@@ -143,5 +143,65 @@ var totalNQueens = function(n) {
return count;
};
```
+
+C
+```c
+//path[i]为在i行,path[i]列上存在皇后
+int *path;
+int pathTop;
+int answer;
+//检查当前level行index列放置皇后是否合法
+int isValid(int index, int level) {
+ int i;
+ //updater为若斜角存在皇后,其所应在的列
+ //用来检查左上45度是否存在皇后
+ int lCornerUpdater = index - level;
+ //用来检查右上135度是否存在皇后
+ int rCornerUpdater = index + level;
+ for(i = 0; i < pathTop; ++i) {
+ //path[i] == index检查index列是否存在皇后
+ //检查斜角皇后:只要path[i] == updater,就说明当前位置不可放置皇后。
+ //path[i] == lCornerUpdater检查左上角45度是否有皇后
+ //path[i] == rCornerUpdater检查右上角135度是否有皇后
+ if(path[i] == index || path[i] == lCornerUpdater || path[i] == rCornerUpdater)
+ return 0;
+ //更新updater指向下一行对应的位置
+ ++lCornerUpdater;
+ --rCornerUpdater;
+ }
+ return 1;
+}
+
+//回溯算法:level为当前皇后行数
+void backTracking(int n, int level) {
+ //若path中元素个数已经为n,则证明有一种解法。answer+1
+ if(pathTop == n) {
+ ++answer;
+ return;
+ }
+
+ int i;
+ for(i = 0; i < n; ++i) {
+ //若当前level行,i列是合法的放置位置。就将i放入path中
+ if(isValid(i, level)) {
+ path[pathTop++] = i;
+ backTracking(n, level + 1);
+ //回溯
+ --pathTop;
+ }
+ }
+}
+
+int totalNQueens(int n){
+ answer = 0;
+ pathTop = 0;
+ path = (int *)malloc(sizeof(int) * n);
+
+ backTracking(n, 0);
+
+ return answer;
+}
+```
+
-----------------------
diff --git a/problems/0096.不同的二叉搜索树.md b/problems/0096.不同的二叉搜索树.md
index d4b8d024..d334a29c 100644
--- a/problems/0096.不同的二叉搜索树.md
+++ b/problems/0096.不同的二叉搜索树.md
@@ -227,7 +227,34 @@ const numTrees =(n) => {
};
```
+C:
+```c
+//开辟dp数组
+int *initDP(int n) {
+ int *dp = (int *)malloc(sizeof(int) * (n + 1));
+ int i;
+ for(i = 0; i <= n; ++i)
+ dp[i] = 0;
+ return dp;
+}
+int numTrees(int n){
+ //开辟dp数组
+ int *dp = initDP(n);
+ //将dp[0]设为1
+ dp[0] = 1;
+
+ int i, j;
+ for(i = 1; i <= n; ++i) {
+ for(j = 1; j <= i; ++j) {
+ //递推公式:dp[i] = dp[i] + 根为j时左子树种类个数 * 根为j时右子树种类个数
+ dp[i] += dp[j - 1] * dp[i - j];
+ }
+ }
+
+ return dp[n];
+}
+```
-----------------------
diff --git a/problems/0129.求根到叶子节点数字之和.md b/problems/0129.求根到叶子节点数字之和.md
index d07d5244..980779c2 100644
--- a/problems/0129.求根到叶子节点数字之和.md
+++ b/problems/0129.求根到叶子节点数字之和.md
@@ -289,7 +289,33 @@ var sumNumbers = function(root) {
};
```
+C:
+```c
+//sum记录总和
+int sum;
+void traverse(struct TreeNode *node, int val) {
+ //更新val为根节点到当前节点的和
+ val = val * 10 + node->val;
+ //若当前节点为叶子节点,记录val
+ if(!node->left && !node->right) {
+ sum+=val;
+ return;
+ }
+ //若有左/右节点,遍历左/右节点
+ if(node->left)
+ traverse(node->left, val);
+ if(node->right)
+ traverse(node->right, val);
+}
+int sumNumbers(struct TreeNode* root){
+ sum = 0;
+
+ traverse(root, 0);
+
+ return sum;
+}
+```
-----------------------
diff --git a/problems/0143.重排链表.md b/problems/0143.重排链表.md
index 4ea9cb97..00622623 100644
--- a/problems/0143.重排链表.md
+++ b/problems/0143.重排链表.md
@@ -439,7 +439,75 @@ var reorderList = function(head, s = [], tmp) {
}
```
+### C
+方法三:反转链表
+```c
+//翻转链表
+struct ListNode *reverseList(struct ListNode *head) {
+ if(!head)
+ return NULL;
+ struct ListNode *preNode = NULL, *curNode = head;
+ while(curNode) {
+ //创建tempNode记录curNode->next(即将被更新)
+ struct ListNode* tempNode = curNode->next;
+ //将curNode->next指向preNode
+ curNode->next = preNode;
+ //更新preNode为curNode
+ preNode = curNode;
+ //curNode更新为原链表中下一个元素
+ curNode = tempNode;
+ }
+ return preNode;
+}
+void reorderList(struct ListNode* head){
+ //slow用来截取到链表的中间节点(第一个链表的最后节点),每次循环跳一个节点。fast用来辅助,每次循环跳两个节点
+ struct ListNode *fast = head, *slow = head;
+ while(fast && fast->next && fast->next->next) {
+ //fast每次跳两个节点
+ fast = fast->next->next;
+ //slow每次跳一个节点
+ slow = slow->next;
+ }
+ //将slow->next后的节点翻转
+ struct ListNode *sndLst = reverseList(slow->next);
+ //将第一个链表与第二个链表断开
+ slow->next = NULL;
+ //因为插入从curNode->next开始,curNode刚开始已经head。所以fstList要从head->next开始
+ struct ListNode *fstLst = head->next;
+ struct ListNode *curNode = head;
+
+ int count = 0;
+ //当第一个链表和第二个链表中都有节点时循环
+ while(sndLst && fstLst) {
+ //count为奇数,插入fstLst中的节点
+ if(count % 2) {
+ curNode->next = fstLst;
+ fstLst = fstLst->next;
+ }
+ //count为偶数,插入sndList的节点
+ else {
+ curNode->next = sndLst;
+ sndLst = sndLst->next;
+ }
+ //设置下一个节点
+ curNode = curNode->next;
+ //更新count
+ ++count;
+ }
+
+ //若两个链表fstList和sndLst中还有节点,将其放入链表
+ if(fstLst) {
+ curNode->next = fstLst;
+ }
+ if(sndLst) {
+ curNode->next = sndLst;
+ }
+
+ //返回链表
+ return head;
+}
+```
-----------------------
diff --git a/problems/0209.长度最小的子数组.md b/problems/0209.长度最小的子数组.md
index 17422ca0..dc1d9f18 100644
--- a/problems/0209.长度最小的子数组.md
+++ b/problems/0209.长度最小的子数组.md
@@ -330,5 +330,55 @@ def min_sub_array_len(target, nums)
end
```
+C:
+暴力解法:
+```c
+int minSubArrayLen(int target, int* nums, int numsSize){
+ //初始化最小长度为INT_MAX
+ int minLength = INT_MAX;
+ int sum;
+
+ int left, right;
+ for(left = 0; left < numsSize; ++left) {
+ //每次遍历都清零sum,计算当前位置后和>=target的子数组的长度
+ sum = 0;
+ //从left开始,sum中添加元素
+ for(right = left; right < numsSize; ++right) {
+ sum += nums[right];
+ //若加入当前元素后,和大于target,则更新minLength
+ if(sum >= target) {
+ int subLength = right - left + 1;
+ minLength = minLength < subLength ? minLength : subLength;
+ }
+ }
+ }
+ //若minLength不为INT_MAX,则返回minLnegth
+ return minLength == INT_MAX ? 0 : minLength;
+}
+```
+
+滑动窗口:
+```c
+int minSubArrayLen(int target, int* nums, int numsSize){
+ //初始化最小长度为INT_MAX
+ int minLength = INT_MAX;
+ int sum = 0;
+
+ int left = 0, right = 0;
+ //右边界向右扩展
+ for(; right < numsSize; ++right) {
+ sum += nums[right];
+ //当sum的值大于等于target时,保存长度,并且收缩左边界
+ while(sum >= target) {
+ int subLength = right - left + 1;
+ minLength = minLength < subLength ? minLength : subLength;
+ sum -= nums[left++];
+ }
+ }
+ //若minLength不为INT_MAX,则返回minLnegth
+ return minLength == INT_MAX ? 0 : minLength;
+}
+```
+
-----------------------
diff --git a/problems/0343.整数拆分.md b/problems/0343.整数拆分.md
index 5d11f670..9882c6ea 100644
--- a/problems/0343.整数拆分.md
+++ b/problems/0343.整数拆分.md
@@ -271,5 +271,40 @@ var integerBreak = function(n) {
};
```
+C:
+```c
+//初始化DP数组
+int *initDP(int num) {
+ int* dp = (int*)malloc(sizeof(int) * (num + 1));
+ int i;
+ for(i = 0; i < num + 1; ++i) {
+ dp[i] = 0;
+ }
+ return dp;
+}
+
+//取三数最大值
+int max(int num1, int num2, int num3) {
+ int tempMax = num1 > num2 ? num1 : num2;
+ return tempMax > num3 ? tempMax : num3;
+}
+
+int integerBreak(int n){
+ int *dp = initDP(n);
+ //初始化dp[2]为1
+ dp[2] = 1;
+
+ int i;
+ for(i = 3; i <= n; ++i) {
+ int j;
+ for(j = 1; j < i - 1; ++j) {
+ //取得上次循环:dp[i],原数相乘,或j*dp[]i-j] 三数中的最大值
+ dp[i] = max(dp[i], j * (i - j), j * dp[i - j]);
+ }
+ }
+ return dp[n];
+}
+```
+
-----------------------