位运算其他应用

位操作进行标识

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的自身特点(后三位不同),不需将其映射为哈希,也可以省一些空间

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值