[算法]力扣刷题-初级算法 - 数组(一) [删除有序数组中的重复项] [买卖股票的最佳时机 II] [轮转数组] [存在重复元素]

初级算法 - 数组篇完结:
初级算法 - 数组(一):
https://blog.csdn.net/weixin_43854928/article/details/121315702

初级算法 - 数组(二):
https://blog.csdn.net/weixin_43854928/article/details/121523946

初级算法 - 数组(三):
https://blog.csdn.net/weixin_43854928/article/details/121568562


26. 删除有序数组中的重复项

给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
示例 2:
输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。
链接:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array

思路:数组已经排好序了,从第0个元素作为对比项(cur_index),对比之后的元素是否与对比项相同,相同则跳过,不相同则更新为对比项,计数count++,并赋值到第count个元素中。
时间复杂度:O(n)
空间复杂度:O(1)

int removeDuplicates(int* nums, int numsSize)
{
    if(numsSize == 0)
    {
        return 0;
    }
    short count = 1;
    short cur_index = 0;

    for(short i = 1; i<numsSize; i++)
    {
        if(nums[i] != nums[cur_index])
        {
            if(count != i)
            {
                nums[count] = nums[i];
            }
            count++;
            cur_index = i;
        }
    }
    return count;

}

122. 买卖股票的最佳时机 II

给定一个数组 prices ,其中 prices[i] 是一支给定股票第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
示例1: 输入: prices = [7,1,5,3,6,4] 输出:
7 解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 =4 。
随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。

链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii

思路:找到山峰和山谷,山峰卖出,山谷买入。山峰的特点是下一个元素开始变小,即为山峰,山谷的特点是下一个元素开始变大,即为山谷。注意最后一个交易日如果不是卖出,要把当前的持有全部卖出。
时间复杂度:O(n)
空间复杂度:O(1)

int maxProfit(int* prices, int pricesSize)
{
    int buy_prices = 0;
    int profit_count = 0;
    char buy_flag = false;
    for(short i = 1; i< pricesSize; i++)
    {
        if(prices[i] > prices[i-1] && !buy_flag)
        {
            buy_prices = prices[i-1];
            buy_flag = true;
        }
        else if(prices[i] < prices[i-1] && buy_flag)
        {
            profit_count += prices[i-1] - buy_prices;
            buy_flag = false;
        }
    }
    if(buy_flag)
    {
        profit_count += prices[pricesSize-1] - buy_prices;
    }
    return profit_count;
}

189. 轮转数组

给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
示例 1: 输入: nums = [1,2,3,4,5,6,7],
k = 3 输出: [5,6,7,1,2,3,4]
解释: 向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步:[6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]
链接:https://leetcode-cn.com/problems/rotate-array

思路:

  1. 先将k对数组长度取余,因为整圈数的轮转没有意义。
  2. 整个数组反转,然后按取余后的temp_k将数组分成前后两部分,两部分再分别反转。
    时间复杂度:O(n)
    空间复杂度:O(1)
void rotate(int* nums, int numsSize, int k)
{
    int temp_k = k%numsSize;
    if(numsSize == 1 || temp_k == 0)
    {
        return;
    }
    for(int i = 0; i<numsSize/2; i++)
    {
        int temp = nums[i];
        nums[i] = nums[numsSize-i-1];
        nums[numsSize-i-1] = temp;
    }
    
    for(int i = 0; i<temp_k/2; i++)
    {
        int temp = nums[i];
        nums[i] = nums[temp_k-i-1];
        nums[temp_k-i-1] = temp;
    }
    
    for(int i = 0; i<(numsSize-temp_k)/2; i++)
    {
        int temp = nums[i+temp_k];
        nums[i+temp_k] = nums[numsSize-i-1];
        nums[numsSize-i-1] = temp;
    }

}

217. 存在重复元素

给定一个整数数组,判断是否存在重复元素。
如果存在一值在数组中出现至少两次,函数返回 true 。如果数组中每个元素都不相同,则返回 false 。
示例 1:
输入: [1,2,3,1]
输出: true
示例 2:
输入: [1,2,3,4]
输出: false
链接:https://leetcode-cn.com/leetbook/read/top-interview-questions-easy/x248f5/

思路:一开始的思路是先把数组排序,排序后从前往后遍历nums[i]和nums[i+1]是否相等。
为了防止执行超时用的快速排序:

void quick_sort(int* low, int* high)
{
    if (low >= high) //排序结束
    {
        return;
    }

    int *i = low, *j = high;
    const int key = *low;

    while(i<j)
    {
        while(*j >= key && i<j)
        {
            j-=1;
        }
        if(*j < key)
        {
            *i = *j;
            *j = key;
            i+=1;
        }

        while(*i <= key && i<j)
        {
            i+=1;
        }
        if(*i > key)
        {
            *j=*i;
            *i = key;
            j-=1;
        }
    }
    quick_sort(low, i-1);
    quick_sort(i+1, high);
}

bool containsDuplicate(int* nums, int numsSize)
{
    if(numsSize<2)
    {
        return false;
    }
    quick_sort(nums, nums+numsSize-1);
    for(int i = 0; i<numsSize-1; i++)
    {
        if(nums[i] == nums[i+1])
        {
            return true;
        }
    }
    return false;
}

结果还是超时了。

没办法只能手写了一个hash map,执行时间满足了要求,但内存占用要高出很多:
在这里插入图片描述

struct hash_node
{
    char flag;
    int number;
    struct hash_node* next;
};

bool add_hash_node(int data_num, int numsSize, struct hash_node* hash_map)
{
    int key = (data_num&0x7FFFFFFF)%numsSize;
    struct hash_node* node = &hash_map[key];
    struct hash_node* next_node = node;

    do
    {
        node = next_node;
        if(!node->flag)//空
        {
            node->number = data_num;
            node->flag = 1;
            return false;
        }
        else
        {
            if(node->number == data_num)
            {
                return true;
            }
        }
        
        next_node = node->next;
    } 
    while(next_node);

    node->next = calloc(1, sizeof(struct hash_node));
    node->number = data_num;
    node->flag = 1;
    return false;
}



bool containsDuplicate(int* nums, int numsSize)
{
    struct hash_node hash_map[numsSize];
    memset(hash_map, 0, sizeof(hash_map));
    for(int i = 0; i< numsSize; i++)
    {
        if(add_hash_node(nums[i], numsSize, hash_map) == true)
        {
            return true;
        }
    }
    return false;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

___NULL___

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值