java关于回溯算法的题1

这篇文章是关于我今天所做的关于回溯算法的题(出自力扣),参考了力扣上几位大牛的算法,在此表示感谢!

  1. 组合总和
  2. 组合总和 II
  3. 组合总和 III
  4. 组合总和 IV
  5. 全排列
  6. 单词搜索
  7. 最大单词长度乘积

1. 组合总和
给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的数字可以无限制重复被选取。
说明:
所有数字(包括 target)都是正整数。
解集不能包含重复的组合。
示例 1:
输入: candidates = [2,3,6,7], target = 7,
所求解集为:
[ [7], [2,2,3]]
示例 2:
输入: candidates = [2,3,5], target = 8,
所求解集为:
[ [2,2,2,2], [2,3,3], [3,5]]

class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> list =new ArrayList<>();
		Arrays.sort(candidates);
		
		findAllCombine(list,candidates,target,0,new ArrayList<Integer>());
		//System.out.println(list);
		return list;
    }
	private static void findAllCombine(List<List<Integer>> list, int[] candidates, int target, int start, ArrayList<Integer> al) {
		//System.out.println("target:"+target);
		if(target<0) {
			return;
		}
		if(target==0) {
			list.add(new ArrayList<Integer>(al));
			return;
		}
		for(int i=start;i<candidates.length;i++) {
			//System.out.println(al);
			if(target<candidates[i]) {
				break;
			}
			al.add(candidates[i]);
			findAllCombine(list,candidates,target-candidates[i],i,al);
			al.remove(al.size()-1);
		}
    }
}

2. 组合总和 II
给定一个数组 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]
]

class Solution {
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        List<List<Integer>> list=new ArrayList<>();
		Arrays.sort(candidates);
		findAllOnly(list,new ArrayList<Integer>(),candidates,target,0);
		//System.out.println(list);
		return list;
        
    }
	private static void findAllOnly(List<List<Integer>> list, ArrayList<Integer> al, int[] candidates, int target, int start) {
		if(target<0) {
			return ;
		}
		if(target==0) {
			if(!list.contains(al)) {
				list.add(new ArrayList<>(al));
			}
			
			return;
		}
		for(int i=start;i<candidates.length;i++) {
			al.add(candidates[i]);
			findAllOnly(list,al,candidates,target-candidates[i],i+1);
			al.remove(al.size()-1);
		}
	}
}

3. 组合总和 III
找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字。
说明:
所有数字都是正整数。
解集不能包含重复的组合。
示例 1:
输入: k = 3, n = 7
输出: [[1,2,4]]
示例 2:

输入: k = 3, n = 9
输出: [[1,2,6], [1,3,5], [2,3,4]]

class Solution {
    public List<List<Integer>> combinationSum3(int k, int n) {
        List<List<Integer>> ls=new ArrayList<>();
		int [] candidates=new int[9];
		for(int i=0;i<9;i++) {
			candidates[i]=i+1;
		}
		//System.out.println(Arrays.toString(candidates));
		//找到九个数中等于n的排列组合
		findEqualN(candidates,ls,new ArrayList<Integer>(),0,n,k);
		//System.out.println(ls);
		return ls;
        
    }
	private static void findEqualN(int[] candidates, List<List<Integer>> ls, ArrayList<Integer> al, int start, int target, int k) {
		if(target<0) {
			return;
		}
		if(target==0) {
			if(al.size()==k) {
				ls.add(new ArrayList<>(al));
			}
			return ;
		}
		for(int i=start;i<candidates.length;i++) {
			if(target<candidates[i]) {
				return;
			}
			al.add(candidates[i]);
			findEqualN(candidates,ls,al,i+1,target-candidates[i],k);
			al.remove(al.size()-1);
		}
	}
}

4. 组合总和 IV
给定一个由正整数组成且不存在重复数字的数组,找出和为给定目标正整数的组合的个数。

示例:

nums = [1, 2, 3]
target = 4

所有可能的组合为:
(1, 1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 3)
(2, 1, 1)
(2, 2)
(3, 1)

请注意,顺序不同的序列被视作不同的组合。

因此输出为 7。
进阶:
如果给定的数组中含有负数会怎么样?
问题会产生什么变化?
我们需要在题目中添加什么限制来允许负数的出现?
注:这是力扣上那位大牛的代码,我没有改

class Solution {
    public int combinationSum4(int[] nums, int target) {
        //dfs会超时
        //使用dp数组,dp[i]代表组合数为i时使用nums中的数能组成的组合数的个数
        //别怪我写的这么完整
        //dp[i]=dp[i-nums[0]]+dp[i-nums[1]]+dp[i=nums[2]]+...
        //举个例子比如nums=[1,3,4],target=7;
        //dp[7]=dp[6]+dp[4]+dp[3]
        //其实就是说7的组合数可以由三部分组成,1和dp[6],3和dp[4],4和dp[3];
        int[]dp=new int[target+1];
        //是为了算上自己的情况,比如dp[1]可以由dp【0】和1这个数的这种情况组成。
        dp[0]=1;
        for(int i=1;i<=target;i++) {
            for(int num:nums){
                if(i>=num) {
                    dp[i]+=dp[i-num];
                }
            }
        }
        return dp[target];
    }
}

5. 全排列
给定一个没有重复数字的序列,返回其所有可能的全排列。

示例:

输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]

class Solution {
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>>arraylist=new ArrayList<>();
    	return recursion(arraylist, nums, 0, nums.length-1);
    	
    }
    	//核心
	    public static List<List<Integer>> recursion(List<List<Integer>> al,int[]nums,int begin,int end){
	    	List<Integer>al2=new ArrayList<>();
	        if(begin==end){
	        	for(int i=0;i<=end;i++){
	        		al2.add(nums[i]);
	        	}
	        	al.add(al2);
	        	return al;
	        }else{
	        	for(int j=begin;j<=end;j++){
	        		exch(nums,begin,j);
	            	recursion(al,nums, begin+1, end);
	            	exch(nums,begin,j);
	        	} 
	        	return al;
	        }
	    }
    	//交换
		private static void exch(int[] nums, int i, int j) {
			int temp=nums[i];
			nums[i]=nums[j];
			nums[j]=temp;
		}
}

6. 单词搜索
给定一个二维网格和一个单词,找出该单词是否存在于网格中。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
示例:
board =
[ [‘A’,‘B’,‘C’,‘E’],[‘S’,‘F’,‘C’,‘S’], [‘A’,‘D’,‘E’,‘E’]]
给定 word = “ABCCED”, 返回 true.
给定 word = “SEE”, 返回 true.
给定 word = “ABCB”, 返回 false.

class Solution {
    public boolean exist(char[][] board, String word) {
         char [] chs=word.toCharArray();
         int rows=board.length;
         int cols=board[0].length;
          boolean [][] visited=new boolean [rows][cols];
         for(int i=0;i<rows;i++) {
        	 for(int j=0;j<cols;j++) {
        		 if(isValid(0,board,i,j,rows,cols,visited,chs)) {
        			return true; 
        		 }
        	 }
         }
		return false;
    }
	private boolean isValid(int index, char[][] board, int row, int col, int rows, int cols, boolean[][] visited, char[] chs) {
		boolean flag=false;
		if(row>=0 && row<rows && col>=0 && col<cols &&
				!visited[row][col] && board[row][col]==chs[index]) {
			index++;
			visited[row][col]=true;
			if(index==chs.length) {
				return true;
			}
			flag=isValid(index,board,row+1,col,rows,cols,visited,chs)||
					isValid(index,board,row-1,col,rows,cols,visited,chs)||
					isValid(index,board,row,col+1,rows,cols,visited,chs)||
					isValid(index,board,row,col-1,rows,cols,visited,chs);
			if(!flag){
				index--;
				visited[row][col]=false;
			}
		}
		return flag;
	}
}

7. 最大单词长度乘积
给定一个字符串数组 words,找到 length(word[i]) * length(word[j]) 的最大值,并且这两个单词不含有公共字母。你可以认为每个单词只包含小写字母。如果不存在这样的两个单词,返回 0。

示例 1:

输入: [“abcw”,“baz”,“foo”,“bar”,“xtfn”,“abcdef”]
输出: 16
解释: 这两个单词为 “abcw”, “xtfn”。
示例 2:

输入: [“a”,“ab”,“abc”,“d”,“cd”,“bcd”,“abcd”]
输出: 4
解释: 这两个单词为 “ab”, “cd”。
示例 3:

输入: [“a”,“aa”,“aaa”,“aaaa”]
输出: 0
解释: 不存在这样的两个单词。

class Solution {
    public int maxProduct(String[] words) {
        //先将所有的单词用32的整数进行表示
		int [] val=new int[words.length];
		for(int i=0;i<words.length;i++) {
			for(char c:words[i].toCharArray()) {
				val[i] |=1<<(c-'a');
			}
		}
		//System.out.println(Arrays.toString(val));
		int max=0;
		//当两个数按位与时,等于0说明没有相同字母
		for(int i=0;i<words.length-1;i++) {
			for(int j=i+1;j<words.length;j++) {
				if((val[i] & val[j])==0) {
					max=Math.max(max,words[i].length()*words[j].length());
				}
			}
		}
		return max;
		
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值