剑指offer刷题经验

3.19

41(1) 输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。

思路:

使用双指针,一个指针指向元素较小的值,一个指针指向元素较大的值。指向较小元素的指针从头向尾遍历,指向较大元素的指针从尾向头遍历。

  • 如果 cursum > sum,移动较大的元素,使 cursum 变小一些;
  • 如果 cursum < sum,移动较小的元素,使 cursum 变大一些。
  • 如果两个指针指向元素的和 sum == cursum,那么得到要求的结果;
public:
    //双指针移动,因为数组有序,所以找到的第一对为积最小的一对
    vector<int> FindNumbersWithSum(vector<int> array,int sum) {
         vector<int> result;
        int len = array.size();
        if(len<=0) return result;;
        int a = 0;
        int b = len-1;
        int cursum =0;
        while(a<b){
            cursum = array[a]+array[b];
            if( cursum > sum ){
                b--;
            }else if(cursum<sum){
                a++;
            }else{
                result.push_back(array[a]);
                result.push_back(array[b]);
               break;
            }
        }  
        return result;
    }

 40(2)小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列?

class Solution {
public:
    vector<vector<int> > FindContinuousSequence(int sum) {
        int a = 1;
        int b = 2;
        int end = (1+sum)/2;//最少有两个数,则a最大到end大小
        int cursum = a+b;
        vector<vector<int> > res;
        while(a<end){
            if(cursum == sum){
                res.push_back(PrintContinuousSequence(a,b));
            }
            while(cursum > sum && a<end){
                cursum -= a;//先将当前最小值减掉,让a+1为下一个最小值。
                a++;
                if(cursum == sum){
                res.push_back(PrintContinuousSequence(a,b));
                }
            }
            b++;
            cursum += b; 
        }
        return res;
    }
    vector<int> PrintContinuousSequence(int start,int end){
        vector<int> result;
        for(int i = start;i<=end;i++){
            result.push_back(i);
        }
        return result;
    }
};

44 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。

思路:先进行排序,再对数组中0的个数和空子的个数进行比较,如果numberOfZero>=cout,则可以注册顺子,否则 , 不能。

其重要考虑出现对子的情况,有对子,则一定不是顺子。

class Solution {
public:
    bool IsContinuous( vector<int> numbers ) {
        int len = numbers.size();
        if(len<=0) return false;
        sort(numbers.begin(),numbers.end());
        int numberOfZero = 0;//数字中0的个数
        for(int i = 0;i< len ;i++){
            if(numbers[i] == 0) numberOfZero++ ;
        }
        int small = numberOfZero;
        int big = small + 1;
        int count = 0;//空子的总数
        while(big<len){
            if(numbers[small] == numbers[big]) //如果有对子,则不是顺子
                return false;
            count = count+(numbers[big]-numbers[small]-1);
            small = big;
            big = big+1;
        }
        //当0的个数大于等于空子的个数则返回真
        return (numberOfZero>=count)?true:false;
    }
};

45 写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。

class Solution {
public:
    int Add(int num1, int num2)
    {
      //分三步计算,第一步num1^num2的值记为sum1;
      //第二步,sum1&&sum2的值再左移一位记为sum2;
      //第三部,将sum1的值赋值给num1,sum2的值赋值给num2。指导num2为0结束循环。
       int sum1,sum2;
        while(num2!=0){
            sum1 = num1^num2;
            sum2 = (num1&num2)<<1;
            num1 = sum1;
            num2 = sum2;
        }
        return num1;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值