LintCode 1679: Lucky Number (排列好题)

  1. Lucky Number

People usually think that a number that only contains 3 or 5 is a lucky number.

Now given an integer n, and you need to find the smallest lucky number that is not less than N and the number of occurrences of 3 in this lucky number is the same as the number of occurrences of 5.

Example
Example 1:

Input: n = “3500”
Output: “3535”
Explanation:
The smallest lucky number is 3533, but the number of occurrences of 3 is not equal to the number of occurrences of 5.
The second smallest lucky number is 3535, and the number of occurrences of 3 is equal to the number of occurrences of 5.
Example 2:

Input: n = “1”
Output: “35”
Notice
1 ≤ n ≤ 10^100000

解法1:
这题不容易。
我参考了一些网上的做法,再加上自己的改进。终于过了。
基本思想是基于next_permutation()函数,但是出发的那个基点minStr选择很有技巧,不然遇到规模大的Input肯定超时。
假设输入是
"51443924594061573070619476735114529340233670970104091717691753660643“
我们考虑3种minStr
minStr =“33333333333333333333333333333333355555555555555555555555555555555555”
minStr2 = “53535353535353535353535353535353535353535353535353535353535353535353”
minStr3 = “53333333333333333333333333333333335555555555555555555555555555555555”
即minStr是333…555…
minStr2是535353…53
minStr3是5333…355…5
显然minStr<minStr3<minStr2
其中minStr3的选择很有技巧,注意第一个字符是5,后面跟len/2个3,然后又跟len/2-1个5。
当n[0]=5时,如果n比minStr大,但是比minStr3小,当然就从minStr3开始找。如果n比minStr3大,但是比minStr2小,就从minStr2开始找。
上面我写的可能不对,现在回想一下,实际上n[0]=5时n肯定比minStr大。理论上如果n比minStr2小,minStr3就应该是出发点,不需要再跟minStr2比较。如果n比minStr2还大,则minStr2是出发点。
2) maxStr=555…53…333.
在next_permutation的循环中,如果超过了maxStr就不要找了。如果超过了还没找到,比如说99, minStr=‘35’, maxStr=‘53’,则在minStr前后加上’3’和’5‘即可。

代码如下:

class Solution {
public:
    /**
     * @param n: the n
     * @return: the smallest lucky number  that is not less than n
     */
    string luckyNumber(string &n) {
        string strN, minStr, maxStr, minStr2, minStr3;
        string result;
        int len = n.size();
        int origLen = len;
        
        bool foundIt = false;
        
        if (len & 0x1) len++; 
        
        for (int i = 0; i < (len >> 1); ++i) {
            minStr = minStr + '3';
            maxStr = maxStr + '5';
        }
        
        for (int i = (len >> 1); i < len; ++i) {
            minStr = minStr + '5';
            maxStr = maxStr + '3';
        }

        if (origLen & 0x1) {
            return minStr;
        }

        if (n[0] == '3') {
            minStr2 = string(len, '3');  //or string midStr(len, '3');
            for (int i = 0; i < len; ++i) {
                if (i & 0x1) minStr2[i] = '5';
            }
            if (n.compare(minStr) > 0 && n.compare(minStr2) < 0) minStr = minStr2;
        }
        
        if (n[0] == '5') {
            minStr2 = string(len, '5');  //or string midStr(len, '5');
            for (int i = 0; i < len; ++i) {
                if (i & 0x1) minStr2[i] = '3';
            }
            minStr3 = string(len, '3');
            minStr3[0] = '5';
            for (int i = (len >> 1) + 1; i < len; ++i) minStr3[i] = '5';
            if (n.compare(minStr) > 0 && n.compare(minStr3) < 0) minStr = minStr3;
            if (n.compare(minStr3) > 0 && n.compare(minStr2) < 0) minStr = minStr2;
        }
        
        
        strN = minStr;
        do {
            if (strN.compare(maxStr) > 0) {
                foundIt = false;
                break;
            }
            
            if (strN.compare(n) >= 0) {
                result = strN;
                foundIt = true;
                break;
            }
        } while(next_permutation(strN.begin(), strN.end()));
        
        if (!foundIt) {
            result = '3' + strN + '5';    
        }   

        return result;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值