OJ题-4月(C/C++基础)

2 篇文章 0 订阅

1旋转数组

要求:
在这里插入图片描述

1.1暴力写法

void rotate(int* nums, int numsSize, int k){
	int kk = k;
	while (kk--)//重复进行
	{
		//旋转一个数字
		int tmp = nums[numsSize - 1];
		for (int i = numsSize - 2; i >= 0; i--)
		{
			nums[i + 1] = nums[i];   //依次向后赋值覆盖,完成后,把最后一位原来的值赋给第一位
		}
		nums[0] = tmp;              //一次循环完成一个数字的旋转
	}
	//这种写法过不了,耗时太久

1.2倒置写法

思路:
在这里插入图片描述

void InversionArray(int* nums, int n)
{
    if (n < 2)
		return;
	int tmp = 0;
	for (int i = 0; i < n / 2; i++)
	{
		tmp = nums[i];
		nums[i] = nums[n - 1 - i];
		nums[n - 1 - i] = tmp;
	}
}
void rotate(int* nums, int numsSize, int k){
    while (k > numsSize)
	{
		k = k - numsSize;
	}
    InversionArray(nums, numsSize - k);
	int *p = &nums[numsSize - k];
	InversionArray(p,k);
	InversionArray(nums, numsSize);
}

2移除元素

在这里插入图片描述

int removeElement(int* nums, int numsSize, int val){
int i = 0;
	while (i<numsSize)
	{
		if (nums[i] == val)
		{
			nums[i] = nums[numsSize - 1];  //用最后一个数字覆盖他
			numsSize--;  //最后一个数字被保存在当前位置,当前位置之前的数字被覆盖,所以,--
			if (nums[i] == val) //如果这个换过来的最后一个数字还是val,再用当前末尾的覆盖,所以什么都不做,也不i++,让此位置进入下一轮循环被检验一次,让他再被替换一次
				;
			else
				i++;       //如果覆盖后并不是val,说明覆盖成功,找下一个是val的位置
		}
		else
			i++;            //当前就不是val所以走下一个
	}
	return numsSize;
}

3 搜索插入位置

在这里插入图片描述

int searchInsert(int* nums, int numsSize, int target)
{
    	int i = 0;
	while (i<numsSize)
	{
		if (nums[i] == target)
			return i;
		else if (nums[i]>target&&(i==0||nums[i - 1] < target))
			break;
		else
			i++;
	}
	return i;
}

4 赎金信

在这里插入图片描述


int CalArray(char* nums)
{
	int i = 0;
	while (nums[i] != 0)
	{
		i++;
	}
	return i;
}

bool canConstruct(char * ransomNote, char * magazine){
    //暴力,每个字母只能用一次
	int objSize = CalArray(ransomNote);
	int souSize = CalArray(magazine);
	int flag = souSize;
	for (int i = 0; i < objSize;i++)
	{
		flag = souSize;
		for(int j = 0;j < souSize;j++)
		{
			if (ransomNote[i] == magazine[j])
			{
				  //相等,找下一个
				magazine[j] = magazine[souSize - 1]; //因为不能重复用,所以对比完就替换掉
				souSize--;
				break;
			}
		}
		if (flag == souSize)//说明obj[i]这个位置上没找到
		{
			return false;
		}
	}
	return true;
}

5 回文

在这里插入图片描述

//判断位数
int judge(int x)
{
	int i = 1;
	while (x / 10 != 0)
	{
		i++;
		x = x / 10;
	}
	return i;
}
bool isPalindrome(int x){
	if (x < 0)
	{
		return false;
	}
	int front = 1;
	int	behind=x;
	int pre = x;
	int flag = judge(x); //5位
	int divisor = 1;
	int i = flag/2;
	while (--flag)
	{
		divisor = divisor * 10;
	}
	while (i--)
	{
		front = (x / divisor)%10;   //取第一个数字
		divisor=divisor/10;
		behind = pre % 10;
		pre = pre / 10;
		if (front == behind)
		{
			;
		}
		else
			return false;
	}
	return true;

}

6 最后一个单词的长度

在这里插入图片描述

int lengthOfLastWord(char * s){
 //如果没有单词返回0
	//特殊情况,最后一个单词末尾有空格
	int i = 0, j = 0; //给两个指针位置
	int flag = 0;
	while (s[j] != 0&&s[i]!= 0)
	{
		while ((s[j] >= 65 && s[j]<=90) || (s[j]>=97 && s[j] <= 122))
		{
			j++;//j位置为字母加加到下一位
		}
		if (s[j] == ' ')
		{
			flag = j;
			while (s[flag] == ' ')
			{
				flag++;
			}

			if (s[flag] == 0)
			{
				return j - i;
			}
			else if ((s[flag] >= 65 && s[flag] <= 90) || (s[flag] >= 97 && s[flag] <= 122))
			{
				j = flag;
				i = j;
		    }	
		
		}
	}
	return j - i;
}

7合并两个有序数组

在这里插入图片描述思路:
在这里插入图片描述

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){
if (m == 0)
	{
		for (int y = 0; y < n; y++)
		{
			nums1[y] = nums2[y];
		}
	}
	if (n == 0)
		return;
	int i = m - 1;
	int j = n - 1;
	int cur = nums1Size - 1;
	while (cur>=0&&(i>=0||j>=0))
	{
		if (i >= 0&&(j<0||nums1[i] > nums2[j]))
		{
			nums1[cur] = nums1[i];
			cur--;
			i--;
		}
		else if (j >= 0 && (i<0||nums1[i] <= nums2[j]))
		{
			nums1[cur] = nums2[j];
			cur--;
			j--;
		}
	}
}

8 长按键入

在这里插入图片描述

bool isLongPressedName(char * name, char * typed){
int i = 0;
	int j = 0;
	while (name[i] == typed[j]&&name[i]!=0)
	{
		i++;
		j++;
		if (name[i] == name[i-1])
			;
		else
		{
			while (typed[j] == typed[j - 1])
			{
				j++;
			}
		}
	}
	if (name[i] == 0 && typed[j] == 0)
	{
		return true;
	}
	return false;
}

在这里插入图片描述
在这里插入图片描述

9有序数组的平方

在这里插入图片描述

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* sortedSquares(int* A, int ASize, int* returnSize){
  int* array = (int*)malloc(sizeof(A[0])*ASize);

	int i = 0;
	int j = 0;
	int cur = 0;

	while (i<ASize&&A[i] < 0)
	{
		i++;
	}

	j = i;
	i = i - 1;

	while(cur<ASize)
	{
		if (i >= 0&&(j>=ASize||abs(A[i]) < abs(A[j])))
		{
			array[cur] = A[i]*A[i];
			i--;
			cur++;
		}
		else if (j < ASize&&(i<0||abs( A[i])>= abs(A[j])))
		{
			array[cur] = A[j]*A[j];
			j++;
			cur++;
		}
	}
	*returnSize = ASize;
	return array;
}

注意:
开始时没有加这三个条件,被判断内存访问。调的人都崩溃了
报错AddressSanitizer: heap-buffer-overflow on address 0x60300000000c at pc 0x000000401c74 bp 0x7ffec50708c0 sp 0x7ffec50708b0
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

10 按奇偶排序树组

在这里插入图片描述
在这里插入图片描述

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* sortArrayByParity(int* A, int ASize, int* returnSize){
  int* array = (int*)malloc(sizeof(int)*ASize);
	int i = 0;
	int j = ASize - 1;
	int tmp = 0;
	while (i < j){
		if (A[i] % 2){  //i在前面,是奇数,待交换
			if (!(A[j] % 2))  //j在后面,是偶数,待交换
			{
				tmp = A[i];
				A[i] = A[j];
				A[j] = tmp;
				i++;
				j--;
			}
			else{    //j位置就是奇数,不需要换
				j--;
			}
		}
		else //i为偶数,不需要换
		{
			i++;
		}
	}
	tmp = ASize;
	while(tmp>=0){
		array[tmp] = A[tmp];
		--tmp;
	}
	*returnSzie = ASize;
	return array;
}

如上代码编译器上完全没问题,OJ上编译不通过,甚至报错,至今不能理解AddressSanitizer: stack-buffer-overflow on address 0x7ffc4bd52af4 at pc 0x000000404fe8 bp 0x7ffc4bd52930 sp 0x7ffc4bd52920

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* sortArrayByParity(int* A, int ASize, int* returnSize){
  int* array = (int*)malloc(sizeof(int)*ASize);
	int cur = 0;
	int head = 0;
	int tail = ASize - 1;
    *returnSize = ASize; //没加这句报了同前面的错
	while (cur >= 0 && cur < ASize){
		if (A[cur] % 2)
		{
			array[tail--] = A[cur++];
		}
		else
		{
			array[head++] = A[cur++];
		}
	}
	return array;

}

11 仅仅反转字母

在这里插入图片描述

int CalArray(char* nums)
{
	int i = 0;
	while (nums[i] != 0)
	{
		i++;
	}
	return i;
}
char * reverseOnlyLetters(char * S){

int head = 0;
	int tail = CalArray(S)-1;
	int tmp = 0;
	while (head<tail)
	{
		if (S[head] >= 65 && S[head] <= 90 || S[head] >= 97 && S[head] <= 122) //头是字母
		{
			if (S[tail] >= 65 && S[tail] <= 90 || S[tail] >= 97 && S[tail] <= 122)  //头尾都是字母,兴奋的交换
			{
				tmp = S[tail];
				S[tail] = S[head];
				S[head] = tmp;
				head++;
				tail--;
			}
			else//头是字母,尾不是
			{
				tail--;
			}
		}
		else if (S[tail] >= 65 && S[tail] <= 90 || S[tail] >= 97 && S[tail] <= 122) //头不是字母,跳过,尾是
		{
			head++;
		}
		else   //头尾都不是字母
		{
			head++;
			tail--;
		}
	}
	return S;
    
}

在这里插入图片描述

12 返回第三大的数字

在这里插入图片描述

int thirdMax(int* nums, int numsSize){
    int first = 0;  //存放最大的数
	int second = 0; //存放第二大的数
	int third = 0;  //存放第三大的数
	int flag1 = 0; //0为first未被初始化,1为first被初始化
	int flag2 = 0;//0为second未被初始化,1为second被初始化
	int flag3 = 0;//为0 表示third没有被初始化
	for (int i = 0; i < numsSize; i++)  //遍历数组
	{
		if ((flag3 ==0||nums[i] >third)&&nums[i]!= second)   //third未被初始化或当前值比third大并且当前值不等于second
		{
			if ((flag2 ==0||nums[i] > second)&&nums[i]!= first)  //second未被初始化或当前值比second大并且当前值不等于first
			{
				if (flag1 ==0||nums[i] > first)  //值比first大的情况
				{
					if (flag2 == 1)      //如果second已经被初始化了,那third也要在这一层被初始化
					{
						flag3 = 1;
					}
					if (flag1 == 1)   //如果first被初始化了,那second也要在这一层被初始化
					{
						flag2 = 1;
					}
					
					third = second;  //比first 大
					second = first;
					first = nums[i];
					flag1 = 1;    //first被当前值初始化
				}
				else
				{
					if (flag2 == 1)
					{
						flag3 = 1;
					}
					third = second;  //比second大,没有first大
					second = nums[i];
					flag2 = 1;
					
				}
				
			}
			else if (nums[i] != first)  //说明不满足(flag2 ==0||nums[i] > second)即second被初始化了,但是当前遍历值还小于second
			{
				third  = nums[i];     //比second小,比third大
				flag3 = 1;
			}
			
		}
	}
	if (flag3 == 0)   //说明没有第三大的数字
		return first;
	return third;
}

在这里插入图片描述

13 中心索引

在这里插入图片描述

int pivotIndex(int* nums, int numsSize){
    if (numsSize == 0)
		return -1;
	if (numsSize == 1)
	{
		return 0;
	}
	int cur = 0;
	int leftSum = 0;
	int rightSum = 0;
	while (cur<numsSize)
	{
		rightSum = rightSum + nums[cur];
		cur++;
	}
	rightSum = rightSum-nums[0];
	for (cur = 0; cur < numsSize; cur++)
	{
		if (leftSum == rightSum)
		{
			return cur;
		}
		else
		{
			if (cur >= numsSize - 2)
			{
				rightSum = 0;
			}
			else{
				rightSum = rightSum - nums[cur + 1];
			}
			leftSum = leftSum + nums[cur];
			
		}
	}
	return -1;
}

在这里插入图片描述

14 加一(数组存只能单个数字,整体加一,完成进位)

在这里插入图片描述

digits[digitsSize - 1] = digits[digitsSize - 1] + 1;
	int i = digitsSize - 1;
	int j = 0;
	while (digits[i] == 10)
	{
		if (i == 0)
		{
			digits[i] = 0;
			int* pre = (int*)malloc((digitsSize + 1)*sizeof(int));
			pre[0] = 1;
			for (j = 1; j < digitsSize + 1; j++)
			{
				pre[j] = digits[j - 1];
			}
			*returnSize = digitsSize + 1;
			return pre;
		}
		digits[i - 1] = digits[i - 1] + 1;
		digits[i] = 0;
		i--;
	}
	*returnSize = digitsSize;
	return digits;

在这里插入图片描述

15 两数之和(数组中找出和为目标值的两个整数)

在这里插入图片描述

//1、暴力解法O(n^2)
int* twoSum(int* nums, int numsSize, int target, int* returnSize)
{
	int* returnpre = (int*)malloc(numsSize*sizeof(int));
	for (int i = 0; i < numsSize; i++)
	{
		for (int j = i + 1; j < numsSize; j++)
		{
			if (nums[i] + nums[j] == target)
			{
				returnpre[0] = i;
				returnpre[1] = j;
			}
		}
	}
	return returnpre;
}

在这里插入图片描述

//2、优质解法,散列数组
#define 2000
int* twoSum(int* nums, int numsSize, int target, int* returnSize)
{
	int i = 0;
	int hash[MAXSIZE];
	int *ret = (int*)malloc(sizeof(int)* 2);
	memset(hash, -1, sizeof(hash));
	for (i = 0; i < numsSize; i++)//找
	{
		if (hash[(target - nums[i] + MAXSIZE) % MAXSIZE] != -1)  //先找再赋值,可以避免找到自身的情况
		{
			ret[0] = i;
			ret[1] = hash[(target - nums[i] + MAXSIZE) % MAXSIZE];
			break;
		}
		hash[(nums[i] + MAXSIZE) % MAXSIZE] = i;
	}
	*returnSize = 2;
	return ret;
}

在这里插入图片描述

思路说明
构造散列数组:
1.将nums数组元素和下标交换构造hash数组,初始赋值全为-1,因为nums数组的下标里不可能有-1。
2.给定MAXSIZE作为hash数组的元素个数,当遇到nums数组的负值时,用MAXSIZE+nums[i],把他放到数组后部分;(nums[i]+MAXSIZE)%MAXSIZE可以让正数不变,负数+MAXSIZE。
3.可能会发生散列冲突,比如nums里有两个及以上相同值,==该值所在的hash数组的对应下标位置(原nums[i]的元素值)的元素值(原nums[i]的下标i)会始终被赋值为最后一次出现该值的nums下标。==但是被覆盖一个位置不影响计算。覆盖两个位置就会无法完整计算,这种情况只能构造更好的散列数组来避免,目前没有彻底的解决方法。

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值