首页 > 其他 > 详细

1286.字母组合迭代器

时间:2021-04-18 14:30:37      阅读:16      评论:0      收藏:0      [点我收藏+]

难度 medium
请你设计一个迭代器类,包括以下内容:

一个构造函数,输入参数包括:一个 有序且字符唯一 的字符串 characters(该字符串只包含小写英文字母)和一个数字 combinationLength 。
函数 next() ,按 字典序 返回长度为 combinationLength 的下一个字母组合。
函数 hasNext() ,只有存在长度为 combinationLength 的下一个字母组合时,才返回 True;否则,返回 False。

示例:

CombinationIterator iterator = new CombinationIterator("abc", 2); // 创建迭代器 iterator

iterator.next(); // 返回 "ab"
iterator.hasNext(); // 返回 true
iterator.next(); // 返回 "ac"
iterator.hasNext(); // 返回 true
iterator.next(); // 返回 "bc"
iterator.hasNext(); // 返回 false

提示:

1 <= combinationLength <= characters.length <= 15
每组测试数据最多包含 10^4 次函数调用。
题目保证每次调用函数 next 时都存在下一个字母组合。

解题思路:我们可以看到按照字典序排序编码如下,长度为2,比如:
abcd
则字典序排序应该是:

ab
ac
ad
bc
bd

刚好可以对应二进制数,从大到小:

1100
1010
1001
0110
0101
0011

观察到以上规律,我们就可以避免求出所有的全排列组合,依次按照二进制编码从大到小的顺序,将所有的字符串依次求出即可。

  1. 所谓的长度,只需要满足二进制编码中1的个数满足要求即可,通过n&(n-1)这种快速的解法很容易求出1的个数.

代码 t72 s90 java

class CombinationIterator {

    public CombinationIterator(String characters, int combinationLength) {
        int sz = characters.length();
        this.cur = (1<<sz) - 1;
        this.size = combinationLength;
        this.key = characters;        
    }
    public int countOne(int n){
        int count = 0, i = 0;
        while(n>0){
            if((n & 1)==1) count++;
            n = n>>1;
        }
        return count;
    }
    public String next() {
        while(cur>0 && countOne(cur)!=size) cur--;
        StringBuilder sb = new StringBuilder();
        for(int i=key.length()-1; i>=0; i--){
            if((cur & (1<<i))>>i==1){
                sb.append(key.charAt(key.length()-1-i));
            }
        }
        cur--;
        return sb.toString();
    }
    
    public boolean hasNext() {
        while(cur>0 && countOne(cur)!=size) cur--;
        if(cur>0) return true;
        return false;
    }

    private int cur;
    private int size;
    private String key;
}

代码 cpp

class CombinationIterator {
public:
    CombinationIterator(string characters, int combinationLength) {
        reverse(characters.begin(),characters.end());
        this->key = characters;
        this->curr = (1<<key.size())-1;
        this->sz = combinationLength;
    }
    
    int countOne(int n){
        int count = 0;
        while (n != 0){
            count++;
            n = (n-1) & n;
        }
        return count;
    }
    
    string next() {    
        while(curr >= 0 && countOne(curr) != sz){
            curr--;
        }
        
        string res;
        for(int i = 0; i < key.size(); ++i){
            if((curr&(1<<i))>>i){ 
                res = key[i] + res;
            }
        }
        curr--;
        
        return res;
    }

    bool hasNext() {  
        while(curr >= 0 && countOne(curr) != sz){curr--;}
        if(curr < 0){
            return false;
        }
        return true;
    }
private:
    int curr;
    int sz;
    int maxCnt;
    string key;
};

参考资料
https://leetcode-cn.com/problems/iterator-for-combination/solution/er-jin-zhi-bian-ma-bu-yong-qiu-chu-quan-pai-lie-by/

1286.字母组合迭代器

原文:https://www.cnblogs.com/zhengxch/p/14673220.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!