《剑指offer》刷题打卡第10天

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

基于Partition函数的时间复杂度为O(n)
代码实现:

class Solution {
public:
    int MoreThanHalfNum_Solution(vector<int> numbers) {
        int n = numbers.size();
        if (n == 0) return 0;
        int num = numbers[0], count = 1;
        for (int i = 1; i < n; i++) {
            if (numbers[i] == num) count++;
            else count--;
            if (count == 0) {
                num = numbers[i];
                count = 1;
            }
        }
        // Verifying
        count = 0;
        for (int i = 0; i < n; i++) {
            if (numbers[i] == num) count++;
        }
        if (count * 2 > n) return num;
        return 0;
    }
};

面试题29:最小的K个数
题目:输入n个整数,找出其中最小的K个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
思路:
解法一:时间复杂度为o(n)的算法,只有当我们可以修改输入的数组时可用
基于Partition函数来解决这个问题,如果基于数组的第K个数字来调整,则使得比第K个数字小的所有数字都位于数组的左边,比第k个数字大的所有数字都位于数组的右边。这样调整之后,位于数组中左边的K个数字就是最小的k个数字(这K个数字不一定是排序的)。
代码实现:

void GetLastNumbers(int *input,int n,int *output,int k)
{
  if(input == nullptr || output == nullptr || k>n || n<=0 || k<=0)
  return;
  
  int start = 0;
  int end = n-1;
  int index = Partition(input,n,start,end);
  while(index != k-1)
  {
  if(index > k-1)
  {
    end = index - 1;
	index = Partition(input,n,start,end);
  }
  else
  {
   start = index + 1;
   index = Partition(input,n,start,end); 
  }
  }
  for(int i = 0;i < k;++i)
  output[i] = input[i];
}

采用这种思路是有限制的。我们需要修改输入的数组,因为函数Partition会调整数组中数字的顺序。
如果面试官要求不能修改输入的数组,那么该怎么办?

解法二:时间复杂度为O(nlogk)的算法,特别适合处理海量数据
我们可以先创建一个大小为k的数据容器来存储最小的k个数字,接下来每次从输入的n个整数中读入一个数。如果容器中已有的数字少于k个,则直接把这次读入的整数放入容器之中;如果容器中已有k个数字了,也就是容器已满,此时我们不能再插入新的数字而只能替换已有的数字。找出这已有的k个数中的最大值,然后拿这次待插入的整数和最大值进行比较。如果待插入的值比当前的已有的最大值小,则用这个数替换当前已有的最大值;如果待插入的值比当前已有的最大值还要大,那么这个数不可能是最小的k个整数之一,于是我们可以抛弃这个整数。

总结:当容器满了之后,我们要做三件事:一是在k个整数中找到最大数;二是有可能在这个容器中删除最大数;三是有可能要插入一个新的数字。
代码实现:

  class Solution {
    public:
        vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
         vector<int> result;
            if(input.size() == 0 || k == 0 || k > input.size())
            {
                return result;
            }
            for(int i = input.size()/2-1;i >= 0;i--)
            {
                adjustHeap(input,i,k);
            }
            
            int i = k;
            while(i < input.size())
            {
                if(input[0] > input[i])
                {
                    int temp = input[i];
                    input[i] = input[0];
                    input[0] = temp;
                    adjustHeap(input,0,k);
                    i = k;
                }
                
                else
                {
                    i++;
                }
            }
            for(int i = 0;i < k;i++)
            {
                result.push_back(input[i]);
            }
            return result;
        }
        void adjustHeap(vector<int>&input,int i,int length)
        {
            int child = i*2+1;
            if(child < length)
            {
                if(child + 1 < length && input[child + 1] > input[child])
            {
                    child = child + 1;
            }
            if(input[child] > input[i])
            {
                int temp = input[i];
                input[i] = input[child];
                input[child] = temp;
                adjustHeap(input,child,length);
            }
        }
        }
        void heapSort(vector<int>&input,int length)
        {
            for(int i = length/2-1;i>=0;i--)
            {
                adjustHeap(input,i,length);
            }
            for(int i = length - 1;i > 0;i--)
            {
                int temp = input[i];
                input[i] = input[0];
                input[0] = temp;
                adjustHeap(input,0,i);
            }
        }
    };

面试题30:连续子数组的最大和
在这里插入图片描述
思路:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
代码实现:

class Solution {
public:
    int FindGreatestSumOfSubArray(vector<int> array) {
    int curSum=array[0];
    int maxSum=array[0];
    for(int i = 1; i < array.size();i++)
    {
        
        curSum += array[i];
        if(curSum < array[i])
            curSum = array[i];
        if(curSum > maxSum)
            maxSum = curSum;
    }
        return maxSum;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值