文章目录
1. 解题报告
题干详见:https://blog.youkuaiyun.com/WhereIsHeroFrom/article/details/120875955
Q1:33. 搜索旋转排序数组
int search(int* nums, int numsSize, int target){
/*情形一:如果numsSize为0,即代表数组为空*/
if(numsSize == 0)
{
return -1;
}
/*case2:numsSize为1*/
if(numsSize == 1)
{
return nums[0]==target ? 0 : -1;
}
/**case 3:numsSize大于1,因为局部有序仍可以使用二分法,只不过是多了一步判断左右那边有序。
*此种数组中数据旋转后,局部有序,此种结构决定其特性:即数组二分为左右部分后,
*至少有一部分满足有序性,而另一部分可能无序,针对无序部分,此特性递归有效。
*二分法套路:
*(1)定义左右需要变量left,right
*(2) while (left <= right){}---如果left > right,代表没找到,退出循环
*(3)“找中点”——int mid = (left + right) / 2;---二分得mid序号
*(4)“判中点”——if (nums[mid] == target) {}---找到目标循环查找结束,否则确保mid定不是target的序号
*(5)“判左”——左半部分有序--if (nums[left] <= target && target < nums[mid]){//}
*(6)“判右”——若右半部分有序--if(numsf[mid] < target && target <= nums[right]){}
*/
int left = 0;
int right = numsSize-1;
while(left<=right)
{
int mid = (left + right)/2;
if(nums[mid] == target)
{
return mid;
}
/*判哪边有序,"="号不可少*/
if(nums[left] <= nums[mid])/*左边有序*/
{
if(nums[left] <= target && target < nums[mid])
{
right = mid - 1;/*缩小范围在左半部分*/
}
else
{
left = mid + 1;/*舍弃左半部分*/
}
}
else/*右边有序*/
{
if(nums[mid] < target && target <= nums[right])
{
left = mid + 1;/*缩小范围在右半部分*/
}
else
{
right = mid - 1;/*舍弃右半部分*/
}
}
}
return -1;
}
Q2: 81. 搜索旋转排序数组 II
bool search(int* nums, int numsSize, int target){
/*情形一:如果numsSize为0,即代表数组为空*/
if(numsSize == 0)
{
return false;
}
/*case2:numsSize为1*/
if(numsSize == 1)
{
return target == nums[0];
}
/**case 3:numsSize大于1,因为局部有序仍可以使用二分法,只不过是多了一步判断左右那边有序。
*此种数组中数据旋转后,局部有序,此种结构决定其特性:即数组二分为左右部分后,
*至少有一部分满足有序性,而另一部分可能无序,针对无序部分,此特性递归有效。
*二分法套路:
*(1)定义左右需要变量left,right
*(2) while (left <= right){}---如果left > right,代表没找到,退出循环
*(3)“找中点”——int mid = (left + right) / 2;---二分得mid序号
*(4)“判中点”——if (nums[mid] == target) {}---找到目标循环查找结束,否则确保mid定不是target的序号
*(5)“判左”——左半部分有序--if (nums[left] <= target && target < nums[mid]){//}
*(6)“判右”——若右半部分有序--if(numsf[mid] < target && target <= nums[right]){}
*/
int left = 0;
int right = numsSize-1;
while(left<=right)
{
int mid = (left + right)/2;
if(nums[mid] == target)
{
return true;
}
/*判哪边有序,非降序存在---特殊情况
*使用if - else if-else的绝佳情景
*/
if(nums[left]==nums[mid]&&nums[mid] == nums[right])
{
++left;
--right;
}
else if(nums[left] <= nums[mid])/*左边有序*/
{
if(nums[left] <= target && target < nums[mid])
{
right = mid - 1;/*缩小范围在左半部分*/
}
else
{
left = mid + 1;/*舍弃左半部分*/
}
}
else/*右边有序*/
{
if(nums[mid] < target && target <= nums[right])
{
left = mid + 1;/*缩小范围在右半部分*/
}
else
{
right = mid - 1;/*舍弃右半部分*/
}
}
}
return false;
}
Q3:153. 寻找旋转排序数组中的最小值
/*Q3-method 1.0*/
int findMin(int* nums, int numsSize){
int min = nums[0];
/*case1:numsSize为1*/
if(numsSize == 1)
{
return nums[0];
}
/**case 2:numsSize大于1,因为局部有序仍可以使用二分法,只不过是多了一步判断左右那边有序。
*/
int left = 0;
int right = numsSize-1;
while(left<=right)
{
int mid = (left + right)/2;
/*判哪边有序*/
if(nums[left] <= nums[mid])/*左边有序*/
{
if(nums[left] <= min)
{
min = nums[left];
left = mid + 1;/*缩小范围在左半部分*/
}
else /*该else分句不可少*/
{
left = mid + 1;
}
}
else/*右边有序,检验完后直接丢弃有序部分*/
{
if(nums[mid] <= min)
{
min = nums[mid];
right = mid - 1;
}
else
{
right = mid -1;
}
}
}
return min;
}
/*Q3_method_2:*/
int findMin(int* nums, int numsSize){
int left = 0;/*隐含数组只有一个值的case*/
int right = numsSize-1;
while(left < right)/*隐含数组不止一个值得情况*/
{
int mid = (left + right)/2;
/*思路:必须是中间值与最右值比较才能入此简洁,
* 如果是中间值与最左值比较,则没有如此简洁
*1)中间值nums[mid]如果小于最右值,则最小值定在中间值序号mid及其以左
*2)中间值nums[mid]如果大于最右值,根据隐含信息,中间值及其以左舍弃,最小值序号定在中间值以右
*3)最终结局找到最小值时,left == right,此时跳出while循环
*/
if(nums[mid] < nums[right])
{
right = mid;
}
else/*右边有序,检验完后直接丢弃有序部分*/
{
left = mid + 1;
}
}
return nums[left];
}
Q4:70. 爬楼梯
int climbStairs(int n){
/*参考题解:我的理解是用了递归思想,回溯,最后一级,要么是一脚踏上来的
,要么是两脚;
每一级台阶都是这么跨上来的,把这种情况累加起来
f(n) = f(n-1) + f(n-2);符合斐波那契数列*/
int p =0;
int q =0;
int r =1;
int i;
for(i = 1;i<=n;++i)
{
p = q;
q = r;
r = p+q;
}
return r;
}
Q5:509. 斐波那契数
/*1)p,q,r构成滚动数组
2)递推关系运用*/
int fib(int n){
int p=0,q=0;
int r = 1;
int i=0;
if(n==0)
{
return 0;
}
else if(n==1)
{
return 1;
}
else{
for(i=2;i<=n;++i)
{
p = q;
q = r;
r = p+q;
}
}
return r;
}
Q6:1137. 第 N 个泰波那契数
int tribonacci(int n){
int p=0,q=0,o=0;/*多了一个数的仿斐波那契数列*/
int r=1;
int i;
if(n == 0)
{
return 0;
}
else if(n == 1)
{
return 1;
}
for(i=2;i<=n;++i)
{
o = p;
p = q;
q = r;
r = p+q +o;
}
return r;
}
Q7:2006. 差的绝对值为 K 的数对数目
int countKDifference(int* nums, int numsSize, int k){
/*思路:从数组的首元素nums[0]到nums[numsSize-1],考虑差值为负的情况
*知识点:二维数组循环遍历
*/
int cnt = 0;
int i,j;
for(i=0;i<numsSize - 1;++i)
{
for(j = i+1;j<numsSize;++j)
{
if(nums[i]-nums[j]==k|| nums[i]-nums[j] ==-k)
{
++cnt;
}
}
}
return cnt;
}
Q8: LCP 01. 猜数字
/*知识点:指针名代表数组名;用指针形式表达数组*/
int game(int* guess, int guessSize, int* answer, int answerSize){
int i=0;
int cnt =0;
for(i=0;i<guessSize;++i)
{
if(*(guess + i) == *(answer + i))
{
++cnt;
}
}
return cnt;
}
Q9:LCP 06. 拿硬币
int minCount(int* coins, int coinsSize){
/*对每一个数组元素,计算其最少次数cnt,在循环中遍历每个元素i,累加求和sum*/
int i = 0;
int sum =0;
int cnt = 0;
for(i = 0;i<coinsSize;++i)
{
if(coins[i]%2 == 0)
{
cnt = coins[i] / 2;
}
else
{
cnt = (coins[i]+1)/2;
}
sum += cnt;
}
return sum;
}
2. 学习报告
(1)初步了解二分法,最关键的是,确定保留有用的部分和舍弃无用的部分。步步为营,不断缩小范围。
(2)了解了斐波那契数列的特点,会用“滚动数组”来求和。
(3)对LeetCode的使用增进了了解