diff --git a/solution/040.Combination Sum II/README.md b/solution/040.Combination Sum II/README.md new file mode 100644 index 0000000000000..7ed110626a30f --- /dev/null +++ b/solution/040.Combination Sum II/README.md @@ -0,0 +1,68 @@ +## 组合总和2 + +### 题目描述 + +给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。 + +candidates 中的每个数字在每个组合中只能使用一次。 + +说明: + +所有数字(包括目标数)都是正整数。 +解集不能包含重复的组合。 + +``` +示例 1: +输入: candidates = [10,1,2,7,6,1,5], target = 8, +所求解集为: +[ + [1, 7], + [1, 2, 5], + [2, 6], + [1, 1, 6] +] + +示例 2: +输入: candidates = [2,5,2,1,2], target = 5, +所求解集为: +[ + [1,2,2], + [5] +] +``` + +### 思路 + +和39题一模一样,注意他有重复数,需要去除重复的结果. + +还要注意回溯是往后回溯,不是原地回溯了 + +```CPP +class Solution { +public: + vector> combinationSum2(vector& candidates, int target) { + vector> ans; + vector tmp; + sort(candidates.begin(),candidates.end()); + int len = candidates.size(); + + dfs(ans,tmp,candidates,target,len,0); + + return ans; + } + + void dfs(vector> &ans,vector &tmp,vector &nums,int target,int len,int index) { + + if(target == 0){ + auto iter = find(ans.begin(),ans.end(),tmp); + if(iter == ans.end())ans.push_back(tmp); + } + + for(int i = index;i= nums[i];i++){ + tmp.push_back(nums[i]); + dfs(ans,tmp,nums,target - nums[i],len,i+1);//注意i+1 + tmp.pop_back(); + } + } +}; +``` \ No newline at end of file diff --git a/solution/040.Combination Sum II/Solution.cpp b/solution/040.Combination Sum II/Solution.cpp new file mode 100644 index 0000000000000..f935d6980e631 --- /dev/null +++ b/solution/040.Combination Sum II/Solution.cpp @@ -0,0 +1,27 @@ +class Solution { +public: + vector> combinationSum2(vector& candidates, int target) { + vector> ans; + vector tmp; + sort(candidates.begin(),candidates.end()); + int len = candidates.size(); + + dfs(ans,tmp,candidates,target,len,0); + + return ans; + } + + void dfs(vector> &ans,vector &tmp,vector &nums,int target,int len,int index) { + + if(target == 0){ + auto iter = find(ans.begin(),ans.end(),tmp); + if(iter == ans.end())ans.push_back(tmp); + } + + for(int i = index;i= nums[i];i++){ + tmp.push_back(nums[i]); + dfs(ans,tmp,nums,target - nums[i],len,i+1);//注意i+1 + tmp.pop_back(); + } + } +}; \ No newline at end of file diff --git a/solution/041.First Missing Positive/README.md b/solution/041.First Missing Positive/README.md new file mode 100644 index 0000000000000..73f08ac52d965 --- /dev/null +++ b/solution/041.First Missing Positive/README.md @@ -0,0 +1,52 @@ +## 缺失的第一个正数 + +### 问题描述 + +给定一个未排序的整数数组,找出其中没有出现的最小的正整数。 + +``` +示例 1: +输入: [1,2,0] +输出: 3 + +示例 2: +输入: [3,4,-1,1] +输出: 2 + +示例 3: +输入: [7,8,9,11,12] +输出: 1 +``` +说明: +你的算法的时间复杂度应为O(n),并且只能使用常数级别的空间。 + +### 思路 + +题目的描述一看有点不好理解,其实是把它们排序后,[-1,1,2,4,4,5,6]这里面缺的第一个正整数是3,0不算正整数 + +1. 对数组排序 +2. 过滤小于等于0的部分 +3. 从1开始比较,注意过滤重复的元素 + +```CPP +class Solution { +public: + int firstMissingPositive(vector& nums) { + sort(nums.begin(),nums.end()); + int len = nums.size(); + if(len == 0)return 1; + int i = 0; + while(nums[i] <= 0 && i < len)i++; + if(i == len)return 1; + + int tmp = 1; + while(ii+1 && nums[i] == nums[i+1])i++;//去重 + i++; + tmp++; + } + return tmp; + } +}; +``` \ No newline at end of file diff --git a/solution/041.First Missing Positive/Solution.cpp b/solution/041.First Missing Positive/Solution.cpp new file mode 100644 index 0000000000000..ea29dcf051581 --- /dev/null +++ b/solution/041.First Missing Positive/Solution.cpp @@ -0,0 +1,20 @@ +class Solution { +public: + int firstMissingPositive(vector& nums) { + sort(nums.begin(),nums.end()); + int len = nums.size(); + if(len == 0)return 1; + int i = 0; + while(nums[i] <= 0 && i < len)i++; + if(i == len)return 1; + + int tmp = 1; + while(ii+1 && nums[i] == nums[i+1])i++;//去重 + i++; + tmp++; + } + return tmp; + } +}; \ No newline at end of file diff --git a/solution/048.Rotate Image/README.md b/solution/048.Rotate Image/README.md new file mode 100644 index 0000000000000..ab73b098abc06 --- /dev/null +++ b/solution/048.Rotate Image/README.md @@ -0,0 +1,89 @@ +## 48旋转图像 + +### 问题描述 +给定一个 n × n 的二维矩阵表示一个图像。 + +将图像顺时针旋转 90 度。 + +说明: + +你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。 +``` +示例 1: +给定 matrix = +[ + [1,2,3], + [4,5,6], + [7,8,9] +], + +原地旋转输入矩阵,使其变为: +[ + [7,4,1], + [8,5,2], + [9,6,3] +] + +示例 2: +给定 matrix = +[ + [ 5, 1, 9,11], + [ 2, 4, 8,10], + [13, 3, 6, 7], + [15,14,12,16] +], + +原地旋转输入矩阵,使其变为: +[ + [15,13, 2, 5], + [14, 3, 4, 1], + [12, 6, 8, 9], + [16, 7,10,11] +] +``` + +### 思路: + +本来以为是矩阵坐标表换的一种,用初等行变换做,但是这里和矩阵坐标没任何关系,而是整个矩阵旋转,所以老实找规律 + +``` +1 2 3 顺90° 7 4 1 +4 5 6 ========> 8 5 2 +7 8 9 9 6 3 + +等价于 + +1 2 3 转置 1 4 7 左右互换 7 4 1 +4 5 6 ========> 2 5 8 ===========> 8 5 2 +7 8 9 3 6 9 9 6 3 + +先当做是一种规律,数学证明以后补 +``` + +1. 先将矩阵转置 +2. 左右各列对称互换 + +```CPP +class Solution { +public: + void rotate(vector>& matrix) { + + int n = matrix.size(); + if(n <= 1)return ; + + //先做转置 + for(int i = 0 ; i < n ; i++){ + for(int j = i;j < n ;j++){ + swap(matrix[i][j],matrix[j][i]); + } + } + + //再做水平互换 + for(int i = 0 ; i < n ; i++){ + for(int j = 0;j < n/2;j++){ + swap(matrix[i][j],matrix[i][n-1-j]); + } + } + } +}; +``` \ No newline at end of file diff --git a/solution/048.Rotate Image/Solution.cpp b/solution/048.Rotate Image/Solution.cpp new file mode 100644 index 0000000000000..5c5418ad91e61 --- /dev/null +++ b/solution/048.Rotate Image/Solution.cpp @@ -0,0 +1,22 @@ +class Solution { +public: + void rotate(vector>& matrix) { + + int n = matrix.size(); + if(n <= 1)return ; + + //先做转置 + for(int i = 0 ; i < n ; i++){ + for(int j = i;j < n ;j++){ + swap(matrix[i][j],matrix[j][i]); + } + } + + //再做水平互换 + for(int i = 0 ; i < n ; i++){ + for(int j = 0;j < n/2;j++){ + swap(matrix[i][j],matrix[i][n-1-j]); + } + } + } +}; \ No newline at end of file diff --git a/solution/112.Path Sum/README.md b/solution/112.Path Sum/README.md new file mode 100644 index 0000000000000..bcfc498b2325c --- /dev/null +++ b/solution/112.Path Sum/README.md @@ -0,0 +1,58 @@ +## 路径总和 + +### 问题描述 + +给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。 + +说明: 叶子节点是指没有子节点的节点。 + +示例: +给定如下二叉树,以及目标和 sum = 22, +``` + 5 + / \ + 4 8 + / / \ + 11 13 4 + / \ \ + 7 2 1 +``` +返回 true, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2。 + + +### 思路 + +题目要求有没有路径到**叶子节点**使和等于目标值 + +主要考察对叶子节点是否判断准确 + +这道题很简单,但是准确率不高,原因是的判断条件不明确,左空右不空返回什么什么,右空左不空返回什么什么,调试一直错 + +叶子节点唯一判断就是左右空 + +`root->left == NULL && root->right==NULL` + +```CPP +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ +class Solution { +public: + bool hasPathSum(TreeNode* root, int sum) { + + if(root == NULL)return false; + if(root->right == NULL && root->left == NULL && sum == root->val)return true; + + bool leftTrue = hasPathSum(root->left,sum - root->val); + bool rightTrue = hasPathSum(root->right,sum - root->val); + + return (leftTrue || rightTrue); + } +}; +``` \ No newline at end of file diff --git a/solution/112.Path Sum/Solution.cpp b/solution/112.Path Sum/Solution.cpp new file mode 100644 index 0000000000000..642a371330813 --- /dev/null +++ b/solution/112.Path Sum/Solution.cpp @@ -0,0 +1,13 @@ +class Solution { +public: + bool hasPathSum(TreeNode* root, int sum) { + + if(root == NULL)return false; + if(root->right == NULL && root->left == NULL && sum == root->val)return true; + + bool leftTrue = hasPathSum(root->left,sum - root->val); + bool rightTrue = hasPathSum(root->right,sum - root->val); + + return (leftTrue || rightTrue); + } +}; \ No newline at end of file