39- 组合总和
给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target
的组合。candidates 中的数字可以无限制重复被选取。
说明:
所有数字(包括 target)都是正整数。 解集不能包含重复的组合。
示例 1:
输入:candidates = [2,3,6,7], target = 7, 所求解集为: [ [7], [2,2,3] ]
回溯法::处理结束条件,可以套模板
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
int len = candidates.length;
List<List<Integer>> res = new ArrayList<>();
if(len==0) return res;
Deque<Integer> path = new LinkedList<>();
dfs(candidates,0,len,target,path,res);
return res;
}
void dfs(int[] candidates, int begin,int len,int target, Deque<Integer> path, List<List<Integer>> res){
if(target<0) return;
if(target==0){
res.add(new LinkedList<>(path));
return;
}
//从begin开始搜索,begin前的数已经被遍历过了
for(int i=begin;i<len;i++){
path.addLast(candidates[i]);
System.out.println("递归之前 => " + path + ",剩余 = " + (target - candidates[i]));
//每一个元素都可以使用因此,begin都是从i开始,递进从在for循环
dfs(candidates,i,len,target-candidates[i],path,res);
//删除添加元素,回到上一个状态,继续向下遍历
path.removeLast();
System.out.println("递归之后 => " + path);
}
}
}
打印是这个样子:
递归之前 => [2],剩余 = 5
递归之前 => [2, 2],剩余 = 3
递归之前 => [2, 2, 2],剩余 = 1
递归之前 => [2, 2, 2, 2],剩余 = -1
递归之后 => [2, 2, 2]
递归之前 => [2, 2, 2, 3],剩余 = -2
递归之后 => [2, 2, 2]
递归之前 => [2, 2, 2, 6],剩余 = -5
递归之后 => [2, 2, 2]
递归之前 => [2, 2, 2, 7],剩余 = -6
递归之后 => [2, 2, 2]
递归之后 => [2, 2]
递归之前 => [2, 2, 3],剩余 = 0
递归之后 => [2, 2]
递归之前 => [2, 2, 6],剩余 = -3
递归之后 => [2, 2]
递归之前 => [2, 2, 7],剩余 = -4
递归之后 => [2, 2]
递归之后 => [2]
递归之前 => [2, 3],剩余 = 2
递归之前 => [2, 3, 3],剩余 = -1
递归之后 => [2, 3]
递归之前 => [2, 3, 6],剩余 = -4
递归之后 => [2, 3]
递归之前 => [2, 3, 7],剩余 = -5
递归之后 => [2, 3]
递归之后 => [2]
递归之前 => [2, 6],剩余 = -1
递归之后 => [2]
递归之前 => [2, 7],剩余 = -2
递归之后 => [2]
递归之后 => []
递归之前 => [3],剩余 = 4
递归之前 => [3, 3],剩余 = 1
递归之前 => [3, 3, 3],剩余 = -2
递归之后 => [3, 3]
递归之前 => [3, 3, 6],剩余 = -5
递归之后 => [3, 3]
递归之前 => [3, 3, 7],剩余 = -6
递归之后 => [3, 3]
递归之后 => [3]
递归之前 => [3, 6],剩余 = -2
递归之后 => [3]
递归之前 => [3, 7],剩余 = -3
递归之后 => [3]
递归之后 => []
递归之前 => [6],剩余 = 1
递归之前 => [6, 6],剩余 = -5
递归之后 => [6]
递归之前 => [6, 7],剩余 = -6
递归之后 => [6]
递归之后 => []
递归之前 => [7],剩余 = 0
递归之后 => []
输出 => [[2, 2, 3], [7]]
作者:liweiwei1419
链接:https://leetcode-cn.com/problems/combination-sum/solution/hui-su-suan-fa-jian-zhi-python-dai-ma-java-dai-m-2/
优化剪枝操作:
剪枝也就是在target小于0之后,就break就不再继续执行本次的for循环。(前提是序列有序)
参考link
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Deque;
import java.util.List;
public class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
int len = candidates.length;
List<List<Integer>> res = new ArrayList<>();
if (len == 0) {
return res;
}
// 排序是剪枝的前提
Arrays.sort(candidates);
Deque<Integer> path = new ArrayDeque<>();
dfs(candidates, 0, len, target, path, res);
return res;
}
private void dfs(int[] candidates, int begin, int len, int target, Deque<Integer> path, List<List<Integer>> res) {
// 由于进入更深层的时候,小于 0 的部分被剪枝,因此递归终止条件值只判断等于 0 的情况
if (target == 0) {
res.add(new ArrayList<>(path));
return;
}
for (int i = begin; i < len; i++) {
// 重点理解这里剪枝,前提是候选数组已经有序,
if (target - candidates[i] < 0) {
break;
}
path.addLast(candidates[i]);
dfs(candidates, i, len, target - candidates[i], path, res);
path.removeLast();
}
}
}
42-接雨水
class Solution {
public int trap(int[] height) {
Stack<Integer> stack = new Stack<Integer>();
int water = 0;
//特殊情况
if(height.length <3){
return 0;
}
for(int i = 0; i < height.length; i++){
while(!stack.isEmpty() && height[i] > height[stack.peek()]){
//栈顶元素
int popnum = stack.pop();
//相同元素的情况例1,1
while(!stack.isEmpty()&&height[popnum] == height[stack.peek()]){
stack.pop();
}
//计算该层的水的单位
if(!stack.isEmpty()){
int temp = height[stack.peek()];//栈顶元素值
//高
int hig = Math.min(temp-height[popnum],height[i]-height[popnum]);
//宽
int wid = i-stack.peek()-1;
water +=hig * wid;
}
}
//这里入栈的是索引
stack.push(i);
}
return water;
}
}
46 - 数字全排列
给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
示例 1:
输入:nums = [1,2,3] 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
示例 2:输入:nums = [0,1] 输出:[[0,1],[1,0]]
class Solution {
public List<List<Integer>> permute(int[] nums) {
int len = nums.length;
List<List<Integer>> res = new ArrayList<>();
if(len==0) return res;
//用来标记数字是否已经被使用过。。如果使用符号标记是否使用就要使用交换法,
//每次交换位置
boolean[] used = new boolean[len];
Deque<Integer> path = new LinkedList<>();
dfs(nums,len,0,path,used,res);
return res;
}
void dfs(int[] nums, int len,int depth,Deque<Integer> path, boolean[] used,List<List<Integer>> res){
if(depth==len){
res.add(new LinkedList<>(path));
return;
}
for(int i=0;i<len;i++){
if(!used[i]){
path.addLast(nums[i]);
used[i]=true;
dfs(nums,len,depth+1,path,used,res);
//取消选择
used[i] = false;
path.removeLast();
}
}
}
}
48-矩阵旋转90度
给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。
你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。
class Solution {
public void rotate(int[][] matrix) {
int len = matrix.length;
if(len<1) return;
int temp;
//先水平翻转
for(int i=0;i<len/2;i++){
for(int j=0;j<len;j++){
temp = matrix[i][j];
matrix[i][j] = matrix[len-1-i][j];
matrix[len-1-i][j] = temp;
}
}
//再转置即可得到答案
for(int i=0;i<len;i++){
//转置转换一个三角即可-->j=i
for(int j=i;j<len;j++){
temp = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = temp;
}
}
}
}
49-字母异位词分组
给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
示例:
输入: [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”] 输出: [
[“ate”,“eat”,“tea”], [“nat”,“tan”], [“bat”] ] 说明:所有输入均为小写字母。 不考虑答案输出的顺序。
使用每个字符中字母出现的频次和对应字母组合作为key,然后统计
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
Map<String,List<String>> map = new HashMap<>();
for(String str:strs){
//记录字符中每个字母出现的次数
int[] counts = new int[26];
int len = str.length();
for(int i=0;i<len;i++){
//如a的ascii是65,则a出现的次数存储在counts[0]
counts[str.charAt(i)-'a']++;
}
//将每个出现次数大于 0 的字母和出现次数按顺序拼接成字符串,作为哈希表的键
//如[a b b c a] 编码之后是a2b2c1
StringBuilder sb=new StringBuilder();
for(int i = 0;i<26;i++){
if(counts[i]!=0){
//保存字母
sb.append((char)('a'+i));
//保存频次
sb.append(counts[i]);
}
}
String key = sb.toString();
//返回key对应的List,然后添加。不存在则new ArrayList<String>
List<String> list = map.getOrDefault(key,new ArrayList<String>());
list.add(str);
map.put(key,list);
}
return new ArrayList<List<String>>(map.values());
}
}