剑指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)。所以算法可以直接简化为只要今天比昨天大,就卖出。