欢迎来到我的世界
希望这篇文章对你有所帮助,有不足的地方还请指正,大家一起学习交流 !
这是暑假题目的收尾文章,我的暑假作业一共写了四篇文章,本篇文章有四篇编程题,我很喜欢四这个数字,感谢铁子们的支持,新的篇章即将来到。
地址:oj地址
解题思路:
暴力求解:分别记录猜中的个数和伪猜中的个数存入数组相应位置。
- 猜中的个数好记录,直接让颜色组合的数组与猜测的数组进行一一比较,如果相等,那猜中的个数++;
- 伪猜中的个数进行两次遍历;第一次遍历颜色组合的数组,在让该数组中的元素都遍历一遍猜测数组元素,如果相等伪猜中个数++,注意:并将猜测数组该位置赋值为空格
' '
这是为了确定唯一性;
注意:这里伪猜中的个数包含了猜中的个数,所以在存入数组的是(伪猜中的个数-猜中的个数)
;
代码实现:
int* masterMind(char* solution, char* guess, int* returnSize) {
*returnSize = 2;//只用两个元素,分别记录猜中个数和伪猜中个数
int* arr = (int*)malloc(sizeof(int) * (*returnSize));
int i = 0;
int sum = 0;//猜中的个数
for (i = 0; i < 4; i++)
{
if (solution[i] == guess[i])
{
sum++;
}
}
arr[0] = sum;
int count = 0;//记录违猜中的个数
int j = 0;
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
{
if (solution[i] == guess[j] )//找到相等的,且将猜测数组中的值该成空格;
{
count++;
guess[j] = ' ';
break;
}
}
}
arr[1] = count - arr[0];
return arr;
}
地址:oj地址
解题思路:
这道题其实也叫做:寻找单身狗
考察的是对按位异或^
的深刻了解:我们首先来了解下
^
他的运算原则是:相同为0
,相异位1
;
在来看到:一个数^
他相同数结果为0
;
假如一个数3
:二进制码:011
;
当3 ^ 3 = 0
所以:3 ^ 0 = 3
;
结论:0 ^
任何数都 = 该数本身,任何数^
该数本身=0
;所以我们可以利用这一特性:
题目中说输入一个数组,该数组只有唯一的一个单着的;
所以让0
按位异或^
上该数组所有数就可以找出那个单着的数;
就像单身狗一样,无所遁形
代码实现:
int main() {
int n=0;
scanf("%d",&n);
int i=0;
int arr=0;
int m=0;//m^上该数组所有元素
for(i=0;i<n;i++)
{
scanf("%d",&arr);
m^=arr;
}
printf("%d",m);
return 0;
}
地址:oj地址
第一个解题思路:暴力求解
根据在数组范围内,只要一个数严格大于两侧的数就为峰值,对nums数组进行遍历,找到一个峰值即可;
暴力求解,代码实现:
int findPeakElement(int* nums, int numsLen ) {
// write code here
int i=0;
if(numsLen==1)//若只有一个值,其本身就是峰值
return 0;
if(nums[0]>nums[1])//若峰值为第一个元素,单独讨论
return 0;
if(nums[numsLen-1]>nums[numsLen-2])//若峰值为最后一个元素,单独讨论
return numsLen-1;
for(i=1;i<numsLen-1;i++)//遍历[1,numsLen-1)范围
{
if(nums[i]>nums[i-1] && nums[i]>nums[i+1])//找到峰值
{
return i;
}
}
return 0;//若还是找不到峰值,就返回0;
}
第二个解题思路:二分思想
在首元素和最后一个为峰值都要单独考虑;
二分思想:设置三个指针left
,right
,找到中间位置的值mid
,然后根据mid
和其两边的值的进行比较,哪边要大于mid
值就往那边找峰值,直到mid
值严格大于其两边的值;
- 如果
nums[mid]
,那么意味这峰值位于 mid
右边,根据二分查找的思想,让left
=mid+1
;- 若
nums[mid]>=nums[mid+1]
,那就意味着峰值位于mid
的左边;根据二分查找的思想,让right
=mid
;- 注意
mid
的值:mid = left + (right - left) / 2;
二分求解,代码实现:
int findPeakElement(int* nums, int numsLen ) {
// write code here
if (numsLen == 1 || nums[0] > nums[1]) return 0;
if (nums[numsLen - 1] > nums[numsLen - 2]) return numsLen - 1;
int left = 0, right = numsLen - 1, mid;
while (left < right) {
mid = left + (right - left) / 2;
if (nums[mid] < nums[mid+1])//中间比右边小,意味着右边肯定有个峰值
left = mid + 1;
else //否则在左边包括当前位置肯定有个峰值
right = mid;
}
return right;
}
地址:oj地址
第一个解题思路:暴力求解
暴力求解:将
x
和y
分别遍历[1, n]
,进行判断当x % y >= k
时统计计数count++
即可,但是这样的话当 n 的值非常大的时候循环次数将非常恐怖,需要循环n^2
次;
注意:这个方法会运行超时;
代码实现:
#include
int main() {
int i=0;
int j=0;
int n,k;
long count=0;
scanf("%d%d",&n,&k);
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if((i%j)>=2)
{
count++;
}
}
}
printf("%ld",count);
return 0;
}
第二个解题思路:
要理解数学公式:
((n/y)*(y-k))+((n%y
;
假如n=10,k=3
;
当y <=k
时,意味着任何数字取模y
的结果都在[0, k-1]
之间,都是不符合条件的。
当y=k+1=4
,x 符合条件的数字有 3,7;
当y=k+2=5
,x 符合条件的数字有 3,4,8,9;所以当
y=k+n
:
x小于y当前值,且符合条件的数字数量是:y-k
个;
x大于y当前值,小于2*y
的数据中,且符合条件的数字数量是:y-k
个;
可以能看出来,在y
的整数倍区间内,x
符合条件的数量就是(n / y) * (y - k)
个;
n / y
表示有多少个完整的0 ~ y
区间,y - k
表示有每个区间内有多少个符合条件的数字;
最后还要考虑的是6...
往后这种超出倍数区间超过n
的部分的统计
n % y
就是多出完整区间部分的数字个数,其中k以下的不用考虑,
则符合条件的是n % y - (k-1)
个。
这里需要注意的是类似于9
这种超出完整区间的数字个数 本就小于k
的情况,则为0
最终公式:(n / y) * (y - k) + ((n % y < k) ? 0, (n % y - k + 1))
;
代码实现:
#include
int main() {
long n,k;
scanf("%ld%ld",&n,&k);
if(k==0)
{
printf("%ld",n*n);
return 0;
}
long count=0;
for(long y=k+1;y<=n;y++)
{
count+=((n/y)*(y-k))+((n%y<k)?0:(n%y-k+1));
}
printf("%ld",count);
return 0;
}
到了最后:感谢支持
我还想告诉你的是:
------------对过程全力以赴,对结果淡然处之
也是对我自己讲的