位操作进行标识
leetcode78 https://leetcode.com/problems/subsets/
Given a set of distinct integers, nums, return all possible subsets.
Note:
Elements in a subset must be in non-descending order.
The solution set must not contain duplicate subsets.
For example,
If nums = [1,2,3], a solution is:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
本题有两个思路:
第一,利用回溯思想递归,一般组合问题【详细归纳见搜索篇】
public List<List<Integer>> subsets(int[] nums) {
Arrays.sort(nums);
List<Integer> ls = new ArrayList<Integer>();
List<List<Integer>> rs = new ArrayList<List<Integer>>();
getPath(nums, 0, rs, ls);
return rs;
}
public void getPath(int[] nums, int p, List<List<Integer>> rs, List<Integer> ls){
List<Integer> tmp = new ArrayList<Integer>(ls);
rs.add(tmp);
for(int i = p; i < nums.length; i++){
ls.add(nums[i]);
getPath(nums, i+1, rs, ls);
ls.remove(ls.size()-1);
}
}
第二,利用位,由于可以将问题看做对于集合中的元素是否选择的问题,因此每个元素存在选择与不选择两种可能,可以用0和1代表这两种情况。那么整体集合的选择情况则可以用一个二进制串来表示每一位的选择情况。
但是该方法有位数限制,int型能表示32个数的集合,long能表示64个数集合。
public List<List<Integer>> subsets(int[] nums) {
Arrays.sort(nums);
int up = 1 << nums.length; //上限值
List<List<Integer>> rs = new ArrayList<List<Integer>>();
for(int i = 0; i < up; i++){
List<Integer> ls = new ArrayList<Integer>();
for(int j = 0; j < nums.length; j++){
if((i & 1 << j) != 0) ls.add(nums[j]); //倒着的
}
rs.add(ls);
}
return rs;
}
位操作进行哈希设计
leetcode187 https://leetcode.com/problems/repeated-dna-sequences/
All DNA is composed of a series of nucleotides abbreviated as A, C, G, and T, for example: "ACGAATTCCG". When studying DNA, it is sometimes useful to identify repeated sequences within the DNA.
Write a function to find all the 10-letter-long sequences (substrings) that occur more than once in a DNA molecule.
For example,
Given s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT",
Return:
["AAAAACCCCC", "CCCCCAAAAA"].
本题的关键在于哈希的策略。设计的哈希策略应该尽量节省空间。
这里目的是将十个长度的串变成唯一标识串作为key存储。由于共四个字母,则可以将每个字母表示为两位位串连成一个整串,共20位。
public List<String> findRepeatedDnaSequences(String s) {
Map<Character, Integer> mp = new HashMap<Character, Integer>();
Set<Integer> rs = new HashSet<Integer>();
Set<String> ls = new HashSet<String>();
mp.put('A',0);mp.put('C',1);mp.put('G',2);mp.put('T',3);
char[] str = s.toCharArray();
int base = 0;
for(int i = 0; i < str.length && i < 10; i++) base = base << 2 | mp.get(str[i]);
rs.add(base);
for(int i = 10; i < str.length; i++){
base = (base << 2 | mp.get(str[i])) & ~0x300000;
if(rs.contains(base)) ls.add(s.substring(i-9, i+1));
else rs.add(base);
}
return new ArrayList<String>(ls);
}
注:也可以只利用ACGT的自身特点(后三位不同),不需将其映射为哈希,也可以省一些空间

1508

被折叠的 条评论
为什么被折叠?



