每日做题之剑指offer(一)

1.二维数组中的查找

时间限制:1秒 空间限制:32768K 热度指数:796670

本题知识点: 查找

题目描述

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

解题思路:例如下面的这个数组,每行每列都是递增排序。如果在这个数组中查找数字7,则返回为true; 如果查找数字5,但是

5不存在这个数组中,返回false.

  • 我们可以根据数组的特性,选择最右上角的数字或者最右下角的数字,此处我们选择最右上角的数字9
  • 9大于7,因为9是该行的最大数字,是这一列所在的最小数字,所以可以去掉9所在的这一列
  • 让7和9这一行前面的数字8进行比较,发现7还是小于8,去掉8所在的这一列(即不用考虑8所在的这一列了)
  • 继续让7和2进行比较,发现7大于2,那么2这一行便没有比较的意义了,去掉2所在的这一行
  • 重复以上步骤即可,也就是所查询的数字小于该数字时,去掉当前比较数字所在的列,大于该数字时,去掉当前比较数字所在的行
class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
		int row=array.size();
        int column=array[0].size();
        int i, j;
        for(i=row-1, j=0; i>=0 && j<column; )
        {   
            if(array[i][j]==target)
                return true;
            if(array[i][j]>target)
            {
                i--;
                continue;
            }
            if(array[i][j]<target)
            {
                j++;
                continue;
	}
};

2.替换空格

时间限制:1秒 空间限制:32768K 热度指数:678309

本题知识点: 字符串

题目描述

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

解题思路

  1. 解题思路一
  • 替换第一个空格,那么后面的字符串整体要向后移动两个位置
  • 替换第二个空格时,也是如此
  • 假设字符串的长度是n, 对于每个空格字符而言, 需要向后移动O(n)个字符
  • 因此对于含有O(n)个空格字符的字符串而言,总体时间效率是O(n2)
  • 但是这个时间复杂度太高了,下面是我们的第二种解法

2.解题思路二

  • 先遍历一次字符串,统计出空格的数量,并且可以计算出字符串的长度
  • 我们发现每替换一个空格,长度加2, 因此替换后的字符串长度等于原字符串的长度加上2*空格数目
  • 如何替换呢?

替换方法:

  • 准备两个指针p1和p2, p1指向原字符串的末尾, p2指向替换后的字符串的末尾
  • 向前移动指针p1,移动的过程中逐个把它只想的字符复制到p2指向的位置,直到遇到第一个空格为止
  • 将空格替换成“%20”, 然后把第一个指针向前移动1,第二个指针向前移动3
  • 替换第二个空格,P1+1, p2+3
  • 逐次向下,直到P1和P2指向同一个位置,表明所有的空格替换完毕
  • 所有的字符都只复制看一次,时间复杂度为O(n)
class Solution {
public:
	void replaceSpace(char *str,int length) {
          if(str == NULL||length<=0)
            return;
        int len = 0;
        int count = 0;
        int i=0;
        while(str[i]!='\0')
        {
            if(str[i]==' ')
                count++;
            len++;
            i++;
        }
         
        int newlen=len+count*2;
        if(length<newlen)
            return;
        int a=len;
        int b=newlen;
        while(a>=0&&b>=0)
        {
            if(str[a]==' ')
            {
                str[b--]='0';
                str[b--]='2';
                str[b--]='%';
            }
            else{
                str[b]=str[a];
                b--;
            }
            a--;
        }
	}
};

3.从尾到头打印链表

时间限制:1秒 空间限制:32768K 热度指数:599489

本题知识点: 链表

题目描述输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。

解题思路:

  • 通常来说打印是一个只读操作,所以最好不要对链表中的内容进行修改
  • 而且通常面试官也不希望我们修改·链表的结构
  • 既然要打印链表,那么我们肯定是要遍历链表的,但是遍历是从前往后的,打印却是从后往前的
  • 由此根据这一性质我们想到了栈“先进后出”的特性
  •  
  • 每经过一个结点,都将其放置到栈中,遍历完整个链表后,再从栈顶开始逐个输出节点的值
/**
*  struct ListNode {
*        int val;
*        struct ListNode *next;
*        ListNode(int x) :
*              val(x), next(NULL) {
*        }
*  };
*/
class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
      vector <int>  result;
      stack<int> nodes;
      ListNode* p = head;
      while(p != NULL)
      {
       nodes.push(p->val);
       p = p->next;
      }
     int len = nodes.size();
     for(int i = 0; i < len ; ++i)
      {
       result.push_back(nodes.top());  
       nodes.pop();
      }
      return  result;
    }
};

递归代码:

void PrintList(ListNode* pHead)
{
	if(pHead != NULL)
	{
		if(pHead->pNext != NULL)
		{
			PrintList(pHead->pNext);
		}
		printf("%d\t", pHead->data);
	}
}

4.重建二叉树

时间限制:1秒 空间限制:32768K 热度指数:404948

题目描述

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

解题思路:

  • 我们都知道,前序遍历的第一个数字总是树的根节点的值;在中序遍历中,根节点位于序列的中间,左边是树的左子树,右边是右子树
  • 因此1是根节点
  • 用同样的方法分别构建左右子树,可以用递归去完成
# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回构造的TreeNode根节点
    def reConstructBinaryTree(self, pre, tin):
        # write code here
        if not pre:
            return None
        root = TreeNode(pre[0])
        i = tin.index(pre[0])
        root.left = self.reConstructBinaryTree(pre[1:i+1], tin[:i])
        root.right = self.reConstructBinaryTree(pre[i+1:], tin[i+1:])
        return root

5.用两个栈实现队列

时间限制:1秒 空间限制:32768K 热度指数:267757

本题知识点: 队列 栈

题目描述

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

解题思路:

  • 队列的特性是“先进先出”
  • 栈的特性是“先进后出”
  • 比如此时我们的队列是“1,2,3,4,5,6,”
  •     
  • 我们将元素压入栈1,但是此时如果想删除1,是不可能的,所以此时栈2就派上了用场
  • 将栈1的元素依次压入栈2,此时最早进入栈1的元素位于栈顶,那么我们就可以删除队列了
  • 如果5和6也入队列的话,重复上述操作
class Solution
{
public:
    void push(int node) {
        stack1.push(node);
    }

    int pop() {
         int res;
        if(stack2.size() > 0)
        {
            res = stack2.top();
            stack2.pop();
        }
        else {
            while(stack1.size() > 0){
                int ele = stack1.top();
                stack1.pop();
                stack2.push(ele);
            }
            res  =  stack2.top();
            stack2.pop();
        }
        return res;
    }
private:
    stack<int>stack1;
    stack<int>stack2;
};
   

6.斐波那切数列

时间限制:1秒 空间限制:32768K 热度指数:361770

题目描述

大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。

n<=39

class Solution {
public:
    int Fibonacci(int n) {
       if(n == 0)
           return 0;
       if(n == 1 || n == 2)
            return 1;
        int a = 1;
        int b = 1;
        int result;
        int i;
      for( i = 3; i <= n; ++i)
        {
            result = a + b;
            a = b;
            b = result;
        }
        return result;
    }
};

猜你喜欢

转载自blog.csdn.net/ijn842/article/details/81538768