一、调整奇数偶数顺序
题目描述:
输入一个整数数组,实现一个函数,来调整该数组中数字的顺序使得数组中所有的奇数位于数组的前半部分,所有偶数位于数组的后半部分
1.思路一(使用多个数组)
我们首先最容易想到的就是创建两个或者三个数组,然后将奇数都放在一个数组里面,将偶数在放在另外一个数组里面,然后将这两个数组进行合并。
①使用两个数组(双指针法)
只使用两个数组的话,第一个数组肯定是我们已经输入好的,第二个数组我们就要用来存放偶数,所以我们需要做的就是,遍历第一个数组,采用两个指针或者两个下标,假设第一个指针p1是来标记目前的奇数的,第二个指针p2就用来标记当前已经遍历到哪里了,那么就当p2找到一个奇数的时候,让p1来存放这个奇数,然后两个指针都向后一走一步,如果遇到的是偶数,那么只让p2走一步,然后将这个偶数放到第二个数组里面,如此循环下去,就可以解决问题。
这样做确实没问题,但是显得过于繁琐,读者可以自行写出代码,代码就不在这里给出了
②使用三个数组
使用了三个数组的话,那么其实思路就更加简单了,第一个数组是用来遍历的,第二个数组用来存放奇数,第三个用来存放偶数,最后这两个数组一合并也能解决问题
思路很简单,读者可以自行写出这个思路的代码
2.思路二(不创建其他的数组,双指针)
这个思路是我们重点需要去了解的,我们前面都创建了数组,那么我们可不可以不创建数组来实现这个呢?答案是可以的
我们是这样想的,我们可以定义两个指针,一个是从left,指向最左边的数组元素,另外一个是right,指向最右边的元素。因为我们是需要让奇数在前,偶数在后,所以我们可以让left从左到右去寻找偶数,找到偶数就停止,然后让right去寻找奇数,找到奇数就停止。这时候我们就得到位置,我们只需要让这两个位置的值进行交换即可。如此循环下去,只要left<right那么就可以一直比较下去。
需要注意的是,里面寻找奇数和偶数的时候也要给他们加上限制条件left<right,否则他们就可能无休止的找下去,一直越界。
代码如下:
#include<stdio.h> #include<assert.h> void adjust_the_order_of_odd_and_even_numbers(int* arr,int sz) { assert(arr); //要求:奇数在全部放在前面,偶数全部放在后面,但不要求顺序 //思路:从前往后找出一个偶数,从后往前找出一个奇数,然后将这两个进行交换即可 int left = 0;//定义出左下标 int right = sz - 1;//定义右下标 while (left < right) { //实现从前往后找偶数 while (left < right) { if (arr[left] % 2 == 0) { //找到了偶数,直接跳出循环即可,left就是偶数的下标 break; } left++; } //实现从后往前找奇数 while (left < right) { if (arr[right] % 2 == 1) { //找到了奇数,直接跳出循环即可,right就是奇数的下标 break; } right--; } //交换奇数和偶数 if (left < right) { int tmp = arr[left]; arr[left] = arr[right]; arr[right] = tmp; } } } int main() { int arr[] = { 5,7,5,1,5,54,5,4546,482 }; int sz = sizeof(arr) / sizeof(arr[0]); adjust_the_order_of_odd_and_even_numbers(arr,sz); int i = 0; for (i = 0; i < sz; i++) { printf("%d ", arr[i]); } return 0; }
运行结果为
二、有序数组合并
来源:牛客网
1.思路一
对于这道题目,我们可以使用最简单最暴力的方法,那就是不管三七二十一,先将这两个数组的元素都放到同一个数组中,然后进行排序。这样做当然是可行的,但是时间就慢了。
2.思路二
我们可以这样思考,先创建这样一个大数组,然后让这两个数组的元素一一比较,谁的元素小,谁先放到第三个数组里面,这样一直循环下去,直到其中一个数组被放完了,然后我们就将另外一个数组的元素全部补到后面即可
代码如下
#include<stdio.h> #include<assert.h> void MergeOrderedArrays(const int* arr1, int n, const int* arr2, int m, int* arr3, int len) { assert(arr1 && arr2 && arr3); int arr1_left = 0; int arr1_right = n - 1; int arr2_left = 0; int arr2_right = m - 1; int arr3_left = 0; int arr3_right = len - 1; while (arr3_left <= arr3_right) { if (arr1_left <= arr1_right && arr2_left <= arr2_right) { //1的左下标是不可以超过他的右下标的 //arr1的元素小于arr2的元素的时候,将arr1的元素放入arr3中,然后arr1_left++,arr3_left++ if (arr1[arr1_left] <= arr2[arr2_left]) { arr3[arr3_left] = arr1[arr1_left]; arr1_left++; arr3_left++; } //2的左下标也是不可以超过他的右下标的 //arr2的元素小于arr1的元素的时候,将arr2的元素放入arr3中,然后arr2_left++,arr3_left++ if (arr1[arr1_left] >= arr2[arr2_left]) { arr3[arr3_left] = arr2[arr2_left]; arr2_left++; arr3_left++; } } else if (arr1_left == arr1_right+1 ) { while (arr2_left <= arr2_right) { arr3[arr3_left] = arr2[arr2_left]; arr2_left++; arr3_left++; } } else if (arr2_left == arr2_right+1 ) { while (arr1_left <= arr1_right) { arr3[arr3_left] = arr1[arr1_left]; arr1_left++; arr3_left++; } } } } int main() { int n = 0; int m = 0; scanf("%d %d", &n, &m); int arr1[1000]; int arr2[1000]; int i = 0; for (i = 0; i < n; i++) { scanf("%d", &arr1[i]); } for (i = 0; i < m; i++) { scanf("%d", &arr2[i]); } int len = m + n; int arr3[2000]; MergeOrderedArrays(arr1, n, arr2, m, arr3, len); for (i = 0; i < len; i++) { printf("%d ", arr3[i]); } return 0; }
运行结果为
三、有序序列判断
来源:牛客网
对于这道题,我们可以使用来个标记来完成,我们先假设这个数组既是升序又是降序的,也就是令flag1和flag2都为1,然后我们在来验证这两个是否是满足升序和降序的条件
我们先验证是否升序,也就是比较n-1次,n为数组元素个数,看看是否每一次都满足前面的元素小于等于后面的元素,只要一次不满足,他就不是升序的。我们就让flag1变为0
然后我们在来判断是否降序,比较n-1次,看看是否每一次都满足后面元素小于等于前面元素,只要有一次不满足,他就不是降序的。我们就让flag2变为0
我们只要满足任何一个flag为1,他就是有序的,只有当两个flag都为0的情况下,他才是无序的
代码为:
#include<stdio.h> int is_sorted(int* arr, int sz) { //默认是有序的 int flag1 = 1; int flag2 = 1; int i = 0; //判断是否是升序的 for (i = 0; i < sz - 1; i++) { if (arr[i] > arr[i + 1]) { flag1 = 0; break; } } //判断是否是降序的 for (i = 0; i < sz - 1; i++) { if (arr[i] < arr[i + 1]) { flag2 = 0; break; } } int flag = flag1 || flag2; return flag; } int main() { int n = 0; scanf("%d", &n); int i = 0; int arr[100]; for (i = 0; i < n; i++) { scanf("%d", &arr[i]); } int ret = is_sorted(arr, n); if (ret == 1) { printf("sorted"); } if (ret == 0) { printf("unsorted"); } return 0; }
运行结果为:
总结
本小节讲解了三个经典的题目,交换奇数偶数次序,有序序列合并以及有序序列判断,希望大家都能理解这三个题目,如果对你有帮助,不要忘记点赞加收藏哦!!!
如果想了解更多C语言系列的精彩讲解,记得关注我哦!!!