缺失数字,回文数,宝石问题,有序数组的平方问题

本文深入探讨了寻找缺失数字的两种方法,包括常规排序法和高效异或法,以及如何判断一个整数是否为回文数,提供了一种不将整数转换为字符串的解决方案。此外,还介绍了如何计算字符串中宝石类型石头的数量,以及如何对有序数组的平方进行排序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

缺失数字

给定一个包含 0, 1, 2, …, n 中 n 个数的序列,找出 0 … n 中没有出现在序列中的那个数。
示例 1:输入: [3,0,1]输出: 2
示例 2:输入: [9,6,4,2,3,5,7,0,1]输出: 8

int missingNumber(int* nums, int numsSize) 
{
}

这道题并不是很难,我们这里说说一种常规解法和一种快速解法:
常规解法一:
首先将这个这个传过来的数组进行排序,因为应该是连续数,所以当相邻两项之差不为1时,我们就可以确定缺失数了:

int missingNumber(int* nums, int numsSize)
{
	int i = 0;
	int j = 0;
	if (numsSize == 1)
	{
		return 1 - nums[0];
	}
	for (i = 0; i<numsSize; i++)
	{
		for (j = 0; j<numsSize - i - 1; j++)
		{
			if (nums[j]>nums[j + 1])
			{
				int temp = nums[j];
				nums[j] = nums[j + 1];
				nums[j + 1] = temp;
			}
		}
	}
	for (i = 0; i<numsSize; i++)
	{
		if (nums[i + 1] - nums[i] != 1)
			return i + 1;
	}
	return 0;
}

特殊解法:
将题目给出的0~n也看成一组数据,在这两组数据里只有缺失的数不是成对的的,所以就可以按位异或的方法快速得到答案:

int missingNumber(int* nums, int numsSize) 
{
    
    int i =0,num=0;
    for(i = 0;i<numsSize;i++)
    {
        num^=nums[i];
        num^=i;
    }
     return num^numsSize;   
}
回文数

判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
示例 1:输入: 121输出: true
示例 2:输入: -121输出: false
解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
示例 3:输入: 10输出: false
解释: 从右向左读, 为 01 。因此它不是一个回文数。
进阶:你能不将整数转为字符串来解决这个问题吗?

 bool isPalindrome(int x){
 }

首先我们先列出一定不是回文数的情况:1,负数;2,最低为0但值并不为0的数,为了提升程序的性能,我们在遇到这些情况直接返回false;对于剩下的数,我们只要将他们的有效位逆序,得到的值如果和原数字相等,那就必定是回文数;如何实现整数的逆序呢,我们抓取num最低位(%10)赋给reverse,*10后将num缩小十倍(/10)再取余再加给reverse,这样一直进行直到原本的最高有效位加到reverse变成了最低位。
我们来看看具体如何实现吧:

 bool isPalindrome(int x)
{
    if(x<0||(x%10==0&&x!=0))
        return false;
    long int x_reverse =0;
    int shang = x;
    while(shang)
     {
         x_reverse = x_reverse*10+shang%10;
         shang/=10;
     }
    if(x==x_reverse)
    {
        return true;
    }
return false;
}
宝石与石头

给定字符串J 代表石头中宝石的类型,和字符串 S代表你拥有的石头。 S 中每个字符代表了一种你拥有的石头的类型,你想知道你拥有的石头中有多少是宝石。
J 中的字母不重复,J 和 S中的所有字符都是字母。字母区分大小写,因此"a"和"A"是不同类型的石头。
示例 1:输入: J = “aA”, S = "aAAbbbb"输出: 3
示例 2:输入: J = “z”, S = "ZZ"输出: 0
注意:S 和 J 最多含有50个字母。J 中的字符不重复。

这里的核心思想就是拿出一个宝石类型,然后在你的所有石头里面找有没有这种宝石,然后换下一个宝石类型再找一边。直到所有的类型都找过了,就得出了你所用拥有的宝石总数:

int numJewelsInStones(char* J, char* S) 
{
    char* S_start = S;
    int count = 0;
    while(*J != '\0')
    {
        while(*S!='\0')
        {
            if(*S==*J){count++;}
            S++;
        }
        S = S_start;
        J++;
    }
    return count;
}
有序数组的平方

给定一个按非递减顺序排序的整数数组 A,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。
示例 1:输入:[-4,-1,0,3,10]输出:[0,1,9,16,100]
示例 2:输入:[-7,-3,2,3,11]输出:[4,9,9,49,121]
提示:1 <= A.length <= 10000;-10000 <= A[i] <= 10000;A 已按非递减顺序排序。

/**
 * Return an array of size *returnSize.//将数组长度给returnsize返回;
 * Note: The returned array must be malloced, assume caller calls free().//只需要使用malloc就行了,free不用你管
 */
int* sortedSquares(int* A, int ASize, int* returnSize)
{}

主要是解决负数平方后值会大于绝对值小于他的正数的问题笔者一共实现了两中解法:无脑暴力排序法,和双指针法。

暴力排序法:

这里就是将所有的元素先平方后放进数组里,再对这个新数组里的元素进行排序:(干就完事了=_=)

int* sortedSquares(int* A, int ASize, int* returnSize)
{
    *returnSize = ASize;
    int i = 0;
    int* return_arr = (int*)malloc(sizeof(int)*ASize);
    for(i = 0;i<ASize;i++)
    {
        *(return_arr+i)=(*(A+i))*(*(A+i));
    }
    for(i = 0;i<ASize;i++)
    {
        for(int j = 0;j<ASize-1-i;j++)
        {
            if(return_arr[j]>return_arr[j+1])
            {
                int temp = return_arr[j];
                return_arr[j]=return_arr[j+1];
                return_arr[j+1] = temp;
            }
        }
    }
    return return_arr;
}

不过无脑总是有代价的,那就是效率及其的底下:
在这里插入图片描述
别人都是几十毫秒,这个跑起来直接3000+…跑过了也感觉很没面子啊=_=,而双指针法就可以很好的改善这种情况:

双指针法:

因为数组元素是升序排列的我们在这里使用两个指针分别指向数组的起始元素和最后一个元素,如果这个数组中存在负数,我们就是使用指向起始元素的正序遍历,这样得到的负数平方值就是从大到小的,而正数呢我们用指向最后一个元素的指针进行倒序遍历,这样的到的正数平方值也是从大到小的,两个指针每拿起一个元素,我们便进行比较,大的那个从新数组后面开始放指针移动一位,小的那个指针不动进行下一轮比较。。。
我们来看具体如何实现:

int* sortedSquares(int* A, int ASize, int* returnSize)
{
    int* back = (int *)malloc(sizeof(int)*ASize);
    int i=0, j =ASize-1;
    int k = ASize-1;
    while(i<=j)
    {
        if(abs(A[i])>abs(A[j]))
        {
            back[k] = A[i]*A[i];
            i++;
            k--;
        }
        else
        {
            back[k] = A[j]*A[j];
            j--;
            k--;
        }
    }
    *returnSize = ASize;
    return back;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值