C语言初级——练习(一)
1、合并两个有序数组
给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。
说明:
初始化 nums1 和 nums2 的元素数量分别为 m 和 n。
你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。
示例:
输入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3
输出: [1,2,2,3,5,6]
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){
//冒泡排序,乱序也可用!!!
for(int i=0;i<n;i++){//合并两个数组
nums1[m+i]=nums2[i];
}
for(int i=m+n-1;i>0;i--){ //冒泡排序
for(int j=0;j<i;j++){
if(nums1[j]>nums1[j+1]){
int tmp=nums1[j];
nums1[j]=nums1[j+1];
nums1[j+1]=tmp;
}
}
}
}
或这采用qsort()
函数的快速排序
int cmp(const void *a, const void *b)
{
return *((int*)a) > *((int *)b);
}
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){
//qsort()快速排序,乱序也可用!!!
for(int i=0;i<n;i++){//合并两个数组
nums1[m+i]=nums2[i];
}
qsort(nums1, m+n, sizeof(int), cmp);
}
2、买卖股票的最佳时机
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。
注意你不能在买入股票前卖出股票。
示例 1:
输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。
示例 2:
输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
int maxProfit(int* prices, int pricesSize){
int profit=0;
//对每个利润进行对比,保留输出最大的利润
for(int i=0;i<pricesSize;i++){
for(int j=i+1;j<pricesSize;j++){
if(prices[j]-prices[i]>profit){
profit=prices[j]-prices[i];
}
}
}
return profit;
}
3、只出现一次的数字
做法:(暴力枚举/记录法/排序法/索引法/二进制异或操作)
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1]
输出: 1
示例 2:
输入: [4,1,2,1,2]
输出: 4
//二进制异或 a^a=0 0^a=a 且满足结合律和交换律
int singleNumber(int* nums, int numsSize){
int xor=0;
for(int i=0;i<numsSize;i++){
xor^=nums[i];
}
return xor;
}
//暴力枚举 缺点:时间复杂度高
int singleNumber(int* nums, int numsSize){
if( numsSize <= 1 ){
return nums[0];
}
int num=0;
for( int i = 0; i < numsSize; ++i ){
int flag = 0;
for(int j = 0; j < numsSize; ++j ){
if( i == j ){
continue;
}
if( nums[i] == nums[j] ){
flag = 1;
break;
}
}
if( flag != 1 ){
break;
}
++num;
}
return nums[num];
}
排序法原理:
//1、先采用排序算法将数组进行由小到大排序,此处可以用冒泡排序或快速排序
//2、然后对比前后两个元素是否一样
//例如:
for(int i=0;i<sizeof(nums)/sizeof(nums[0];i+=2)){
if(nums[i]!=nums[i+1])break;
if(i+1>=numsSize)break;
}
//3、返回下标 i 对应的元素
4、只出现一次的数字 II
做法:(暴力枚举/记录法/排序法/索引法//三进制异或操作)
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,3,2]
输出: 3
示例 2:
输入: [0,1,0,1,0,1,99]
输出: 99
int singleNumber(int* nums, int numsSize){
int i,j,k,flag=0;
if(numsSize==1)
return nums[0];
for(i=0;i<numsSize;i++)
{
for(j=0;j<numsSize;j++)
{
if(nums[i]==nums[j]&&i!=j)
{
flag=0;
break;
}
else if(nums[i]!=nums[j])
{
k=nums[i];
flag=1;
}
}
if(flag==1)
break;
}
return k;
}
//排序法,使用qsort()函数进行快速排序,然后三指针滑窗对比
int cmp(const void *a, const void *b)
{
return *((int*)a) > *((int *)b);
}
int singleNumber(int* nums, int numsSize){
qsort(nums, numsSize, sizeof(int), cmp);
int i;
for (i = 0; i < numsSize; i += 3) {
if (i + 1 >= numsSize) break;
if (nums[i] != nums[i+1]) break;
}
return nums[i];
}
三进制异或:
由于计算机的异或默认是二进制的,而二进制的异或是将元素的每位按位相加然后对2取余(满二不进位),所以采用三进制的异或需要将元素的每位按位相加然后对3取余(满三不进位)。
5、缺失数字
做法: (暴力枚举/数组索引/二进制异或操作)
给定一个包含 0, 1, 2, …, n 中 n 个数的序列,找出 0 … n 中没有出现在序列中的那个数。
示例 1:
输入: [3,0,1]
输出: 2
示例 2:
输入: [9,6,4,2,3,5,7,0,1]
输出: 8
//二进制异或 将nums中的元素对0~numsSize进行异或,得出0~numsSize中缺失的元素。
int missingNumber(int* nums, int numsSize){
int xor = 0;
for (int i = 0; i < numsSize; i++) {
xor ^= nums[i];
xor ^= i;
}
xor ^= numsSize;
return xor;
}
/*
思路2:对数组进行排序(从小到大),然后从0开始循环,判断nums中的值是否等于下标
*/
int cmp(const void *a, const void *b)
{
return *((int*)a) > *((int *)b);
}
int missingNumber(int* nums, int numsSize){
int i = 0;
qsort(nums, numsSize, sizeof(int), cmp);
for (i = 0; i < numsSize; i++) {
if (nums[i] != i) {
return i;
}
}
//如果没有找到,说明缺失的最后一个值
return i;
}