Skip to content

Create Solution 048[CPP] #65

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions solution/040.Combination Sum II/README.md
Original file line number Diff line number Diff line change
@@ -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<vector<int>> combinationSum2(vector<int>& candidates, int target) {
vector<vector<int>> ans;
vector<int> tmp;
sort(candidates.begin(),candidates.end());
int len = candidates.size();

dfs(ans,tmp,candidates,target,len,0);

return ans;
}

void dfs(vector<vector<int>> &ans,vector<int> &tmp,vector<int> &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<len && target >= nums[i];i++){
tmp.push_back(nums[i]);
dfs(ans,tmp,nums,target - nums[i],len,i+1);//注意i+1
tmp.pop_back();
}
}
};
```
27 changes: 27 additions & 0 deletions solution/040.Combination Sum II/Solution.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
class Solution {
public:
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
vector<vector<int>> ans;
vector<int> tmp;
sort(candidates.begin(),candidates.end());
int len = candidates.size();

dfs(ans,tmp,candidates,target,len,0);

return ans;
}

void dfs(vector<vector<int>> &ans,vector<int> &tmp,vector<int> &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<len && target >= nums[i];i++){
tmp.push_back(nums[i]);
dfs(ans,tmp,nums,target - nums[i],len,i+1);//注意i+1
tmp.pop_back();
}
}
};
52 changes: 52 additions & 0 deletions solution/041.First Missing Positive/README.md
Original file line number Diff line number Diff line change
@@ -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<int>& 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(i<len){
if(nums[i] != tmp)return tmp;
while(len>i+1 && nums[i] == nums[i+1])i++;//去重
i++;
tmp++;
}
return tmp;
}
};
```
20 changes: 20 additions & 0 deletions solution/041.First Missing Positive/Solution.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
class Solution {
public:
int firstMissingPositive(vector<int>& 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(i<len){
if(nums[i] != tmp)return tmp;
while(len>i+1 && nums[i] == nums[i+1])i++;//去重
i++;
tmp++;
}
return tmp;
}
};
89 changes: 89 additions & 0 deletions solution/048.Rotate Image/README.md
Original file line number Diff line number Diff line change
@@ -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<vector<int>>& 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]);
}
}
}
};
```
22 changes: 22 additions & 0 deletions solution/048.Rotate Image/Solution.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
class Solution {
public:
void rotate(vector<vector<int>>& 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]);
}
}
}
};
58 changes: 58 additions & 0 deletions solution/112.Path Sum/README.md
Original file line number Diff line number Diff line change
@@ -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);
}
};
```
13 changes: 13 additions & 0 deletions solution/112.Path Sum/Solution.cpp
Original file line number Diff line number Diff line change
@@ -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);
}
};