BitMask 相关 318, 1461, 137, 2741, 3097, 136,

318. Maximum Product of Word Lengths

Given a string array words, return the maximum value of length(word[i]) * length(word[j]) where the two words do not share common letters. If no such two words exist, return 0.

 Example 1:

Input: words = ["abcw","baz","foo","bar","xtfn","abcdef"]
Output: 16
Explanation: The two words can be "abcw", "xtfn".

Example 2:

Input: words = ["a","ab","abc","d","cd","bcd","abcd"]
Output: 4
Explanation: The two words can be "ab", "cd".

Example 3:

Input: words = ["a","aa","aaa","aaaa"]
Output: 0
Explanation: No such pair of words. 

Constraints:

  • 2 <= words.length <= 1000
  • 1 <= words[i].length <= 1000
  • words[i] consists only of lowercase English letters.

暴力解法

class Solution {
    public int maxProduct(String[] words) {
        int max = 0;
        for(int i=0;i<words.length-1;i++){
            for(int j=i+1;j<words.length;j++){
                if(!hasCommon(words[i],words[j]))
                    max = Math.max(max,words[i].length()*words[j].length());
            }
        }
        return max;
    }
    private boolean hasCommon(String w1,String w2){
        for(char c : w1.toCharArray()){
            if(w2.indexOf(c)>=0) return true;
        }
        return false;
    }
}

 

巧用bitmask,将 字符串比对 过程从O(len2) 到 O(1), 最终时间复杂度: O(N*N+L) N为字符串个数,L为字符串长度

class Solution {
    public int maxProduct(String[] words) {
        int max = 0;
        int[] state = new int[words.length];
        for(int i=0;i<words.length;i++){
            state[i] = getState(words[i]);
        }
        for(int i=0;i<words.length-1;i++){
            for(int j=i+1;j<words.length;j++){
                if( (state[i] & state[j]) ==0 )
                    max = Math.max(max,words[i].length()*words[j].length());
            }
        }
        return max;
    }
    private int getState(String str){
        int mask = 0;
        for(char c:str.toCharArray()){
            int pos = c-'a';
            mask |= 1<<(pos);
        }
        return mask;
    }
}

bitmask 基础上增加 map对重复字符串集合进行去重,减少比对次数

class Solution {
    public int maxProduct(String[] words) {
        int max = 0;
        Map<Integer,Integer> map = new HashMap();
        
        for(int i=0;i<words.length;i++){
            int bitValue = getState(words[i]);
            map.put(bitValue, Math.max(map.getOrDefault(bitValue,0), words[i].length()));
        }
        int result = 0;
        for(int i:map.keySet()){
            for(int j:map.keySet()){
                if( i!=j && ( (i & j) == 0))
                result = Math.max(result, map.get(i)*map.get(j));
            }
        }
        return result;
    }
    private int getState(String str){
        int mask = 0;
        for(char c:str.toCharArray()){
            int pos = c-'a';
            mask |= 1<<(pos);
        }
        return mask;
    }
}
1461. Check If a String Contains All Binary Codes of Size K
Medium

Given a binary string s and an integer k, return true if every binary code of length k is a substring of s. Otherwise, return false.

 

Example 1:

Input: s = "00110110", k = 2
Output: true
Explanation: The binary codes of length 2 are "00", "01", "10" and "11". They can be all found as substrings at indices 0, 1, 3 and 2 respectively.

Example 2:

Input: s = "0110", k = 1
Output: true
Explanation: The binary codes of length 1 are "0" and "1", it is clear that both exist as a substring. 

Example 3:

Input: s = "0110", k = 2
Output: false
Explanation: The binary code "00" is of length 2 and does not exist in the array.

 

Constraints:

  • 1 <= s.length <= 5 * 105
  • s[i] is either '0' or '1'.
  • 1 <= k <= 20

关键点:使用二进制移位,保持滑动窗口的值 

class Solution {
    public boolean hasAllCodes(String s, int k) {
        int len = 1<<k;
        boolean[] stats = new boolean[len];
        int allOne = len-1;
        int curr = 0;
        for(int i=0;i<s.length();i++){
            int flag = s.charAt(i)-'0';
            curr = ( (curr<<1) & allOne ) + flag;
            if(i>=k-1){
                stats[curr] = true;   
            }
        }
        for(int i=0;i<len;i++){
            if(!stats[i]) return false;
        }
        return true;
    }
}
class Solution {
    public boolean hasAllCodes(String s, int k) {
        int len = 1<<k;
        boolean[] stats = new boolean[len];
        int allOne = len-1;
        int curr = 0;
        for(int i=0;i<s.length();i++){
            int flag = s.charAt(i)-'0';
            curr = ( (curr<<1) & allOne ) + flag;
            if(i>=k-1 && !stats[curr]){
                len--;
                stats[curr] = true;
                if(len==0) return true;
            }
        }
        return false;
    }
}

 

137. Single Number II
Medium

Given an integer array nums where every element appears three times except for one, which appears exactly once. Find the single element and return it.

You must implement a solution with a linear runtime complexity and use only constant extra space.

Example 1:

Input: nums = [2,2,3,2]
Output: 3

Example 2:

Input: nums = [0,1,0,1,0,1,99]
Output: 99

Constraints:

  • 1 <= nums.length <= 3 * 104
  • -231 <= nums[i] <= 231 - 1
  • Each element in nums appears exactly three times except for one element which appears once.
解法:
class Solution {
    public int singleNumber(int[] nums) {
        int result = 0;
        //轮训32个比特位
        for(int i=0;i<32;i++){
            int count = 0;
            //轮询所有数字,看当前比特位是否位1
            for(int num:nums){
                if(((1<<i) & num)!=0 )
                count++;
            }
            //将个数count%3
            result += (count%3)<<i;
        }
        return result;
    }
}

 

1239. Maximum Length of a Concatenated String with Unique Characters
Medium

You are given an array of strings arr. A string s is formed by the concatenation of a subsequence of arr that has unique characters.

Return the maximum possible length of s.

A subsequence is an array that can be derived from another array by deleting some or no elements without changing the order of the remaining elements.

 Example 1:

Input: arr = ["un","iq","ue"]
Output: 4
Explanation: All the valid concatenations are:
- ""
- "un"
- "iq"
- "ue"
- "uniq" ("un" + "iq")
- "ique" ("iq" + "ue")
Maximum length is 4.

Example 2:

Input: arr = ["cha","r","act","ers"]
Output: 6
Explanation: Possible longest valid concatenations are "chaers" ("cha" + "ers") and "acters" ("act" + "ers").

Example 3:

Input: arr = ["abcdefghijklmnopqrstuvwxyz"]
Output: 26
Explanation: The only string in arr has all 26 characters.

 Constraints:

  • 1 <= arr.length <= 16
  • 1 <= arr[i].length <= 26
  • arr[i] contains only lowercase English letters.
 
解法二:bitmask + dfs backtracking
class Solution {
    int max = 0;
    public int maxLength(List<String> arr) {
        List<Integer> list = new ArrayList();
        for(String str:arr) stringToBit(str, list);
        dfs(0, list, 0);
        return max;
    }
    //将字符串转换为比特位,如果自身已经出现重复,那么不加入list
    private void stringToBit(String str, List<Integer> list){
        int result = 0;
        for(char c : str.toCharArray()){
            if((result & 1<<(c-'a')) != 0) return;
            result |= (1<<(c-'a'));
        }
        list.add(result);
    }
    private void dfs(int start, List<Integer> list, int curr){
        max = Math.max(max, Integer.bitCount(curr));
        if(start == list.size()) return;
        for(int i = start;i < list.size(); i++){
            int item = list.get(i);
            //如果有重复则返回
            if((item & curr)!=0) continue;
            //如果没有重复,继续下一个元素
            dfs(i+1, list, curr|item);
        }
    }
}

 1318. Minimum Flips to Make a OR b Equal to c

Medium

Given 3 positives numbers ab and c. Return the minimum flips required in some bits of a and b to make ( a OR b == c ). (bitwise OR operation).
Flip operation consists of change any single bit 1 to 0 or change the bit 0 to 1 in their binary representation.

 Example 1:

Input: a = 2, b = 6, c = 5
Output: 3
Explanation: After flips a = 1 , b = 4 , c = 5 such that (a OR b == c)

Example 2:

Input: a = 4, b = 2, c = 7
Output: 1

Example 3:

Input: a = 1, b = 2, c = 3
Output: 0

 Constraints:

  • 1 <= a <= 10^9
  • 1 <= b <= 10^9
  • 1 <= c <= 10^9

解法:

1.我们要求a|b=c, 那么我们可以通过 a | b ^ c 得到 (a|b) 与 c不同的地方,都是需要flip的

2.还有当a和b都为1,而c为0,这种情况我们需要flip两次, (a & b) & ( a | b ^ c )

将两种相加即是最终结果

class Solution:
    def minFlips(self, a: int, b: int, c: int) -> int:
        return bin((a | b) ^ c).count("1") + bin((a & b) & (( a | b) ^ c)).count("1")

 

2741. Special Permutations
Medium

You are given a 0-indexed integer array nums containing n distinct positive integers. A permutation of nums is called special if:

  • For all indexes 0 <= i < n - 1, either nums[i] % nums[i+1] == 0 or nums[i+1] % nums[i] == 0.

Return the total number of special permutations. As the answer could be large, return it modulo 109 + 7.

 

Example 1:

Input: nums = [2,3,6]
Output: 2
Explanation: [3,6,2] and [2,6,3] are the two special permutations of nums.

Example 2:

Input: nums = [1,4,3]
Output: 2
Explanation: [3,1,4] and [4,1,3] are the two special permutations of nums.

 

Constraints:

  • 2 <= nums.length <= 14
  • 1 <= nums[i] <= 109
class Solution {
    int mod = 1000000000 + 7;
    public int specialPerm(int[] nums) {
        int count = nums.length;
        long total = 0;
        Map<String, Long> countMap = new HashMap();
        long bitMask = 0;
        total = dfs(new boolean[nums.length], count, nums, countMap, bitMask, -1);
        return (int)(total % mod);
    }
    
    private long dfs(boolean[] visited, int count, int[] nums, Map<String, Long> memo, long bitMask, int pre) {
        //如果数字都填完了,返回1
        if(count == 0) return 1;
        long total = 0;
//这个地方为啥要加pre, 是因为我们要保证之前的数字跟当前场景可以整除 String str
= pre + "," + bitMask; //如果已经计算过这种场景,直接返回 if(memo.containsKey(str)) return memo.get(str); for(int i = 0; i < visited.length; i++) { //逐个数字判定是否用过,前提是可以与前面的数字整除 if(!visited[i] && (pre % nums[i] == 0 || nums[i] % pre == 0)) { visited[i] = true; bitMask = bitMask | (1<<i); total += dfs(visited, count - 1, nums, memo, bitMask, nums[i]); visited[i] = false; bitMask = bitMask & ~(1<<i); } } memo.put(str, total); return total % mod; } }

 

3097. Shortest Subarray With OR at Least K II

You are given an array nums of non-negative integers and an integer k.

An array is called special if the bitwise OR of all of its elements is at least k.

Return the length of the shortest special non-empty subarray of numsor return -1 if no special subarray exists.

Example 1:

Input: nums = [1,2,3], k = 2

Output: 1

Explanation:

The subarray [3] has OR value of 3. Hence, we return 1.

Example 2:

Input: nums = [2,1,8], k = 10

Output: 3

Explanation:

The subarray [2,1,8] has OR value of 11. Hence, we return 3.

Example 3:

Input: nums = [1,2], k = 0

Output: 1

Explanation:

The subarray [1] has OR value of 1. Hence, we return 1.

Constraints:

  • 1 <= nums.length <= 2 * 105
  • 0 <= nums[i] <= 109
  • 0 <= k <= 109
class Solution {
    public int minimumSubarrayLength(int[] nums, int k) {
        int left = 1, right = nums.length;
        int result = -1;
        while(left <= right) {
            int mid = left + (right - left) / 2;
            if(check(nums, mid, k)) {
                result = mid;
                right = mid - 1;
            }
            else {
                left = mid + 1;
            }
        }
        return result;
    }

    private boolean check(int[] nums, int len, int k) {
        int curr = 0;
        // 保存各二进制位为1的个数
        int[] count = new int[31];
        for(int i = 0; i < nums.length; i++) {
            // 当前数字各二进制位+1
            for(int j = 0; j < 31; j++) {
                count[j] += (nums[i] >> j) & 1;
            }
            // 当已经收集超过len个数字时,需要将前面的剔除掉
            if(i >= len) {
                for(int j = 0; j < 31; j++) {
                    count[j] -= (nums[i - len] >> j) & 1;
                }
            }
            // 收集够len个的时候,可以开始判定
            if(i >= len - 1) {
                int val = 0;
                // 还原数字的value
                for(int j = 0; j < 31; j++) {
                    if(count[j] > 0) val += (1 << j);
                }
                // System.out.println(len + ":" +  i + ":"+val);
                if(val >= k) return true;
            }
        }
        return false;
    }
}

 

Given a non-empty array of integers nums, every element appears twice except for one. Find that single one.

You must implement a solution with a linear runtime complexity and use only constant extra space.

Example 1:

Input: nums = [2,2,1]

Output: 1

Example 2:

Input: nums = [4,1,2,1,2]

Output: 4

Example 3:

Input: nums = [1]

Output: 1 

Constraints:

  • 1 <= nums.length <= 3 * 104
  • -3 * 104 <= nums[i] <= 3 * 104
  • Each element in the array appears twice except for one element which appears only once.
class Solution {
    public int singleNumber(int[] nums) {
        int result = 0;
        for(int num : nums) {
            result = result ^ num;
        }
        return result;
    }
}

 

posted @ 2022-05-30 00:47  xiaoyongyong  阅读(68)  评论(0)    收藏  举报