C++算法学习3

剑指offer数据结构题1

1.寻找数组中相同的数字

1.把数字交换到和他的值相等的下标中
2.如果一个数字和与其值相等的下标中存储的数字相等,证明有重复

//找出数组中重复的数字:
bool duplicate(int numbers[] , int length , int *duplication)
{
    if(numbers == nullptr||length <= 0)
    {
        return false;
    }
    for(int i = 0 ; i < length ; i++)
    {
        if(numbers[i] < 0 || numbers[i] > length - 1)
            return false;
    }
    for(int i  = 0 ; i < length ; i++)
    {
        if(numbers[i] == numbers[numbers[i]])
        {
            *duplication = numbers[i];
            return true;
        }
        int temp = numbers[i];
        numbers[i] = numbers[numbers[i]];
        numbers[numbers[i]] = temp;
    }
    return false;
}

2.不修改数组找出重复的数字

  • 方法一:使用一个辅助数组,将数字复制到辅助数组中与其值相等的下标处
  • 方法二:二分的思想,将数组分成两部分,分别统计数字出现的次数,如果出现次数超过了这部分的长度,则一定有重复

方法二代码

int countRange(const int * numbers , int length , int start , int end)
{
    if(numbers == nullptr)
        return 0;
    int count = 0;
    for(int i = 0 ; i < length ; i ++ )
    {
        if(numbers[i] >= start && numbers[i] <= end)
            count ++;
    }
    return count;
}
int getDuplication(const int* numbers , int length)
{
    if(numbers == nullptr||length <= 0)
        return -1;
    int start = 1;//最小数字
    int end = length - 1;//最大数字
    while(end >= start)
    {
        int middle = (end-start)/2 + start;
        int count = countRange(numbers , length , start , middle);
        if(end == start)
        {
            if(count > 1)
                return start;
            else
                break;
        }
        if(count > end - start + 1)
            end = middle;
        else
            start = middle + 1;
        
    }
    return -1;
}

杨辉三角2

给定一个非负索引 k,其中 k ≤ 33,返回杨辉三角的第 k 行。
也可以建立一个杨辉三角,再返回最后一行tran.back()

class Solution {
public:
    vector<int> getRow(int rowIndex) {
     vector<int> res(rowIndex + 1);
     if(rowIndex > 33) 
       return res;
     for(int i = 0 ; i <= rowIndex ; i++)
     {
         for(int j = i ; j >= 0 ; j--)
         {
            if(j == 0 || j == i)
                res[j] = 1;
            else
            {
                
                res[j] = res[j] + res[j-1];
            }
         }
         
     }
        return res;
    }
};

求众数

给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在众数。
示例 1:
输入: [3,2,3]
输出: 3
示例 2:
输入: [2,2,1,1,1,2,2]
输出: 2

class Solution {
public:
    int majorityElement(vector<int>& nums) {
    int length = nums.size();
    int count = 1;
    int res = nums[0];    
    for(int i = 1 ; i < length ; i++)
    {
        if(nums[i] != res)
            count--;
        else 
            count ++;
        if(count == 0)
        {
            res = nums[i];
            count++;
        }
        
    }
      return res;  
    }
};

买卖股票的最佳时机

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例 1:
输入: [7,1,5,3,6,4]
输出: 7
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。
示例 2:
输入: [1,2,3,4,5]
输出: 4
解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。
因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。
示例 3:
输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。

我的解法:暴力解:

class Solution {
public:
    int maxProfit(vector<int>& prices) {
     int length = prices.size();
     int i = 0 , j = 1 , sum = 0;
     while(i < length - 1 && j < length)
     {
         if(prices[j] < prices[i])
         {
             i++,j++;
         }
         else
         {
             if(j == length - 1)
             {
                 int temp = prices[j] - prices[i];
                 sum += temp;
                 i = j + 1 , j = i + 1;
             }
             else if(prices[j + 1] > prices[j] && j < length - 1)
                 j++;
             else if(prices[j + 1] <= prices[j])
             {
                 int temp = prices[j] - prices[i];
                 sum += temp;
                 i = j + 1 , j = i + 1;
             }
         }
     }
        return sum;
    }
};

大佬的解法
[7, 1, 5, 6] 第二天买入,第四天卖出,收益最大(6-1),所以一般人可能会想,怎么判断不是第三天就卖出了呢? 这里就把问题复杂化了,根据题目的意思,当天卖出以后,当天还可以买入,所以其实可以第三天卖出,第三天买入,第四天又卖出((5-1)+ (6-5) === 6 - 1)。所以算法可以直接简化为只要今天比昨天大,就卖出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值