扑克牌顺子

题目描述

LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)…他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子…..LL不高兴了,他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。LL决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何, 如果牌能组成顺子就输出true,否则就输出false。为了方便起见,你可以认为大小王是0。

思路

顺子可以看成抽出5个数字,最大最小值差值不大于5,且没有重复的数字。加上大王和小王设为0,0可以重复。

代码

class Solution {
public:
    bool IsContinuous( vector<int> numbers ) {
        if(numbers.empty())
            return false;
        int count[14] = {0};
        int max = -1, min = 14;
        for(int i=0; i<numbers.size();i++){
            if(numbers[i]==0)//0是可以有重复的,所以检测到0直接continue,不需要记录其count
                continue;
            count[numbers[i]]++;
            if(count[numbers[i]]>1)
                return false;
            if(numbers[i] < min)
                min = numbers[i];
            if(numbers[i] > max)
                max = numbers[i];
        }
        return max-min < 5 ;
    }
};

孩子们的游戏(圆圈中剩下的数字)

题目描述

每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0…m-1报数….这样下去….直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!^_^)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)

如果没有小朋友,请返回-1

思路

使用了一个vector来时,当符合计数条件时,直接移除这个数据,最后vector大小为1的时候,就是找到了幸运星。中间要设置好每次删除一个标号,以便于下一个循环删除从该标号开始。

代码

class Solution {
public:
    int LastRemaining_Solution(int n,int m){
        if(n<1||m<1) return -1;
        if(n==1)
            return 0;
        vector<int> child(n);
        for(int i=0;i < n;i++){
            child[i] = i;
        }
        int temp = 0;
        while(child.size()>1){
            int count = temp + m -1; //从上一次删除开始继续数
            int num = count % (child.size());
            temp = num;
            child.erase(child.begin()+num);
        }
        return child[0];
    }
};

求1+2+3+…+n

题目描述

求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。

思路

利用逻辑与的最短路特性,&&就是逻辑与,逻辑与有个短路特点,前面为假,后面不计算。

代码

class Solution {
public:
    int Sum_Solution(int n) {
        int ans = n;
        ans && (ans += Sum_Solution(n-1));
        return ans;
    }
};

把字符串转换成整数

题目描述

将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0

输入描述:

输入一个字符串,包括数字字母符号,可以为空

输出描述:

如果是合法的数值表达则返回该数字,否则返回0

示例1

输入

+2147483647
    1a33

输出

2147483647
    0

思路

主要难点在于如何处理int越界的情况

合理利用 INT_MAX/10
数值越界,即大于 2147483647,或小于 -2147483648。通过观察程序结构,我们发现,每次循环时 value 的值都会扩大10倍(乘以10),
那么,我们是否就可以利用 INT_MAX/10 的值来提前一步判断是否会越界呢?这里我们以正数的越界为例进行解释:

当 value > INT_MAX/10 时,说明本轮扩大10倍后,value 必将越界(超过 INT_MAX);
当 value == INT_MAX/10 时,说明扩大10倍后,value 可能越界,也可能不越界,需要利用当前的加数 digit 来进行进一步的判断:
当 digit > 7 时(以正数为例),越界;负数则是digit >8, 越界;
否则,当 value < INT_MAX/10 时,本轮循环必不越界(扩大10倍后也小于 INT_MAX);

代码

class Solution {
public:
    int StrToInt(string str) {
        int len = str.size(), sign = 1;
        int res = 0;
        if(len<=0)
            return 0;
        if(str[0]=='-')
            sign = -1;
        int overValue;
        for(int i = ((str[0]=='-'||str[0]=='+')? 1 : 0);i<len;i++){
            int digital = str[i]-'0';
            if(str[i]<'0'||str[i]>'9')
                return 0;
            overValue = res - INT_MAX/10;
            if(overValue<0)
                res = res*10 + digital;
            else if(overValue==0){
                if(digital + (sign+1)/2 > 8 )//由于整数负数比较的不同,要加sign一起计算
                    return 0;
                else
                    res = res*10 + digital;
            }else
                return 0;
        }
        return sign*res;
    }
};

剪绳子

题目描述

给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],…,k[m]。请问k[0]xk[1]x…xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。

输入描述:

输入一个数n,意义见题面。(2 <= n <= 60)

输出描述:

输出答案。

示例1

输入

8

输出

18

思路

题目分析:
先举几个例子,可以看出规律来。
4 : 22
5 : 2
3
6 : 33
7 : 2
23 或者43
8 : 233
9 : 333
10:2233 或者433
11:2
333
12:3333
13:2
2333 或者4333
下面是分析:
首先判断k[0]到k[m]可能有哪些数字,实际上只可能是2或者3。
当然也可能有4,但是4=22,我们就简单些不考虑了。
5<2
3,6<33,比6更大的数字我们就更不用考虑了,肯定要继续分。
其次看2和3的数量,2的数量肯定小于3个,为什么呢?因为2
22<33,那么题目就简单了。
直接用n除以3,根据得到的余数判断是一个2还是两个2还是没有2就行了。
由于题目规定m>1,所以2只能是11,3只能是21,这两个特殊情况直接返回就行了。

乘方运算的复杂度为:O(log n),用动态规划来做会耗时比较多。

代码

class Solution {
public:
    int max_cut_3(int number){
        if(number == 2)
            return 1;
        if(number == 3)
            return 2;
        int x = number%3;
        int y = number/3;
        if(x == 0){
            return pow(3, y);
        }else if(x == 1){
            return 2 * 2 * pow(3, y-1);
        }else{
            return 2 * pow(3, y);
        }
    }
    int cutRope(int number) {
        if(number<2)
            return 0;
        int res = max_cut_3(number);
        return res;
    }
};


实习      C++ 牛课网

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!