LeetCode:回溯算法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/oqkdws/article/details/81410259

(1)电话号码的字母组合

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

示例:

输入:"23"
输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].

说明:
尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。

public class CombinationOfTelephoneNumbers {
	public List<String> letterCombinations(String digits) {
		List<String> list = new ArrayList<String>();
		if (digits.length() == 0) {
			return list;
		}
		backtracking("", digits, 0, list);

		return list;

	}

	public static void backtracking(String s, String digits, int flag, List<String> list) {
		String[] strings = { "", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz" };
		if (flag >= digits.length()) {
			list.add(s);
			return; //返回,向上回溯
		}

		String chars = strings[digits.charAt(flag) - '0'];
		for (int i = 0; i < chars.length(); i++) {
			backtracking(s+chars.charAt(i),digits,flag+1,list);
		}
	}
	public static void main(String[] args) {
		String s = "23";
		List<String> la = new CombinationOfTelephoneNumbers().letterCombinations(s);
		System.out.println(la);
	}
}

百度百科:

回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。

(2)生成括号

给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。

例如,给出 = 3,生成结果为:

[
  "((()))",
  "(()())",
  "(())()",
  "()(())",
  "()()()"
]
public class Brackets {
	public List<String> generateParenthesis(int n) {
		List<String> list = new ArrayList<String>();
        bracketsCombination("", list, n, n);
		return list;

	}

	public void bracketsCombination(String sublist, List<String> list, int left, int right) {
		if (left == 0 && right == 0) {
			list.add(sublist);
			return;
		}

		if (left > 0) {
			bracketsCombination(sublist + '(', list, left - 1, right);
		}
		if (right > left) {
			bracketsCombination(sublist + ')', list, left, right - 1);
		}

	}
	
	public static void main(String[] args) {
		int n = 2;
		List<String> la = new Brackets().generateParenthesis(n);
		System.out.println(la);
	}
}

(3)全排列

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

示例:

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

public class FullArrangement {
	public List<List<Integer>> permute(int[] nums) {

		List<List<Integer>> lists = new ArrayList<List<Integer>>();
		List<Integer> list = new ArrayList<Integer>();
		backTracking(lists, list, nums);
		return lists;

	}

	public static void backTracking(List<List<Integer>> lists, List<Integer> list, int[] nums) {

		if (list.size() == nums.length) {
			lists.add(new ArrayList<>(list));
			return;
		} else {
			for (int i = 0; i < nums.length; i++) {
				if (list.contains(nums[i]))
					continue;
				list.add(nums[i]);
				backTracking(lists, list, nums);
				list.remove(list.size() - 1);
			}
		}

	}

	public static void main(String[] args) {
		int[] nums = { 1, 2 };
		List<List<Integer>> lists = new FullArrangement().permute(nums);
		System.out.println(lists);

	}
}

(4)子集

给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

说明:解集不能包含重复的子集。

示例:

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

public class AllSubset {
	public List<List<Integer>> subsets(int[] nums) {
		List<List<Integer>> result = new ArrayList<List<Integer>>();
		List<Integer> temp = new ArrayList<Integer>();
		dfs(result, temp, nums, 0);
		return result;

	}
	 public static void dfs(List<List<Integer>> result, List<Integer> temp, int nums[], int j){
		 
	        result.add(new ArrayList<Integer>(temp));//添加到结果集中
	 
	        for (int i = j; i < nums.length; i++) {
	            temp.add(nums[i]);//添加第i个数进入temp中
	            dfs(result,temp,nums,i+1);//将temp添加到结果集中并添加下一个数
	            temp.remove(temp.size()-1);//把最新添加的一个数删掉继续循环
	        }//循环完返回上一层递归
	    }


	 public static void main(String[] args) {
		 int[] nums = {1,2,3};
		 List<List<Integer>> ls = new AllSubset().subsets(nums);
		 System.out.println(ls);
	}
}

(5)单词搜索

给定一个二维网格和一个单词,找出该单词是否存在于网格中。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

示例:

board =
[
  ['A','B','C','E'],
  ['S','F','C','S'],
  ['A','D','E','E']
]

给定 word = "ABCCED", 返回 true.
给定 word = "SEE", 返回 true.
给定 word = "ABCB", 返回 false.

待续。。。

说明:回溯法,感觉没什么经验的挺难想到的,我也是看别人的代码,自己debug看看是怎么个回溯过程,学到了。return比较叼,到底回到之前哪个点的状态,还是自己debug跟踪一下哦!刷题,感觉和考数学似的,分门别类,多写多学多debug,电脑思维和我们还是不一样。做数学题的时候,一般都是先自己看看会不会,不会看看答案,因为有些有技巧的,然后理解了,自己在操作一遍,真真切切的搞懂了,慢慢的会产生思维定式,这样遇到类似的题才会反应速度快了,然后才叫:刷题!

@@刷起来!!@@

猜你喜欢

转载自blog.csdn.net/oqkdws/article/details/81410259
今日推荐