剑指offer题解

题目描述

在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

思路:这题较好的思路有两个,一个是最容易想到的nlog,枚举行,二分列。另一种就是从左下角逐步枚举,如果大于目标值就向上走,小于目标值就向右走,这样每次2选1最多走n步,复杂度O(n),之所以不能从常规的左上,因为左上都是行列递增的,无法抉择,左下或者右上行列走势不同,可以唯一确定路径

代码:

class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
        int tx = array.size()-1;
        int n = array[0].size();
        int ty = 0;
        while(1)
        {
            if(tx < 0 || ty >= n) break;
            if(array[tx][ty] > target) tx--;
            else if(array[tx][ty] < target) ty++;
            else 
            {
                return true;
                break;
            }
        }
        return  false;
    }
};

题目描述

请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

没什么好说的,注意他题目其实让你把str变成最后的答案。。 也可以从前往后数几个空格,然后从后往前替换,每个字符都要往后移动2*cnt个位置,cnt是这个字符前面的空格数。

void replaceSpace(char *str,int length)
{
    char tmp[1000];
    for(int i = 0; i < length; i++)
        tmp[i] = str[i];
    tmp[length] = '\0';
    int index = 0;
    for(int i = 0; i < length; i++)
          {
              if(tmp[i] == ' ')
                 str[index++] = '%', str[index++] = '2', str[index++] = '0';
              else
                  str[index++] = tmp[i];
//             cout << str << "&&&&" << tmp <<endl;
          }
        str[index] = '\0';
	}

 

题目描述

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

递归+短路特性

int Sum_Solution(int n) {
        int ans = n;
        ans && (ans = ans + Sum_Solution(n-1));
        return ans;
    }

题目描述

一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

原来只能跳1个2个其实就是个简单dp递推式,这个思路还蛮多的

思路1:一眼dp优化,前缀优化下就好了

思路2:每个台阶都有跳与不跳两种情况(除了最后一个台阶),最后一个台阶必须跳。所以共用2^(n-1)中情况

思路3:f(n)=f(n-1)+f(n-2)+...+f(1),因为f(n-1)=f(n-2)+f(n-3)+...+f(1),所以f(n)=2*f(n-1)
代码:

int jumpFloorII(int number) 
    {
        int sum = 0;
        int dp[500];
        dp[0] = 1;
        dp[1] = 1;
        dp[2] = 2;
        sum = 3;
        for(int i = 3; i <= number; i++)
        {
            dp[i] = sum + 1;
            sum += dp[i];
        }
        return dp[number];
    }

题目描述

我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

思路:一看这道题让我想到了当年做匹配问题的时候233  画图看看,发现这个跟青蛙只能跳1,2个格子题目一样,dp[i]代表i之前有多少种放法,你要么竖着放,占一列,要么横着放占两列(放两个) 转移方程一目了然

  int rectCover(int number) {
        int dp[500];
        dp[1] = 1; dp[2] = 2;
        for(int i = 3; i <= number; i++)
            dp[i] = dp[i-1] + dp[i-2];
        return dp[number];
    }

题目描述

给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。

思路:面试题可能不会考你各种算法,算法的变形,都会考你细节,考一些坑,比如这个。。。没告诉你ex的正负号。。你要自己去分类,剩下的就是快速幂了

  double Power(double base, int exponent) {
        double ans = 1, tmp = 1;
        int a = abs(exponent);
        while(a)
        {
            if(a & 1) ans = ans * base;
            a >>= 1;
            base *= base;
        }
        return exponent < 0 ? 1/ans : ans;
    }

题目描述

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

思路:也算是一个经典题了,最后记得跑一下全部看看他是不是超过了一半,因为最后剩下的不是众数,就是最后的数

public:
    int MoreThanHalfNum_Solution(vector<int> numbers) {
        int num = 0, res = 0, len = numbers.size(), maxx = 0;
        for(int i = 0; i < len; i++)
        {
            if(res == numbers[i]) num++;
            else
            {
                if(num > 0) num--;
                if(num == 0) res = numbers[i], num = 1;
            }
        }
        for(int i = 0; i < len; i++)
        {
            if(numbers[i] == res)
                maxx++;
        }
        return maxx > len/2 ? res : 0;
    }

题目描述

HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。你会不会被他忽悠住?(子向量的长度至少是1)

思路:经典的最大连续字段和

int FindGreatestSumOfSubArray(vector<int> array) {
        int sum = 0, len = array.size(), maxx = -1000000000;
        for(int i = 0; i < len; i++)
        {
            sum += array[i];
            maxx = max(maxx, sum);
            if(sum < 0) sum = 0;
        }
        return maxx;
    }

题目描述

把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。

思路:丑数肯定是丑数*丑数来的,第一个是1,那么我们肯定从1*2,1*3,1*5找一个最小的,是2,那么已经确定好顺序的丑数有1,2,这时候应该找2*2,1*3,1*5哪个最小了,可以发现2不会再跟1乘一遍了,所以要有3个变量记录之前哪个丑数分别被2,3,5乘过就好了

int GetUglyNumber_Solution(int index) {
        if(index == 0) return 0;
        int a[index+5], pos2 = 1, pos3 = 1, pos5 = 1, ans = 1;
        a[1] = 1;
        for(int i = 2; i <= index; i++)
        {
            a[i] = min(a[pos2]*2, min(a[pos3]*3, a[pos5]*5));
            if(a[i] == a[pos2]*2) pos2++;
            if(a[i] == a[pos3]*3) pos3++;
            if(a[i] == a[pos5]*5) pos5++;
        }
        return a[index];
    }

题目描述

用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。

 

思路:讨论区一个大神讲的很清楚了

用两个栈实现一个队列的功能?要求给出算法和思路!

<分析>:

入队:将元素进栈A

出队:判断栈B是否为空,如果为空,则将栈A中所有元素pop,并push进栈B,栈B出栈;

 如果不为空,栈B直接出栈。

用两个队列实现一个栈的功能?要求给出算法和思路!

<分析>:

入栈:将元素进队列A

出栈:判断队列A中元素的个数是否为1,如果等于1,则出队列,否则将队列A中的元素   以此出队列并放入队列B,直到队列A中的元素留下一个,然后队列A出队列,再把   队列B中的元素出队列以此放入队列A中。

class Solution
{
public:
    void push(int node) 
    {
        stack1.push(node);
    }
 
    int pop() 
    {
        if(stack2.empty())
        {
            while(!stack1.empty())
            {
                stack2.push(stack1.top());
                stack1.pop();
            }
        }
        int t = stack2.top();
        stack2.pop();
        return t;
    }
 
private:
    stack<int> stack1;
    stack<int> stack2;
};

 

 

 

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值