⭐博客主页:️CS semi主页
⭐欢迎关注:点赞收藏+留言
⭐系列专栏:百日大刷题
⭐代码仓库:C Advanced
家人们更新不易,你们的点赞和关注对我而言十分重要,友友们麻烦多多点赞+关注,你们的支持是我创作最大的动力,欢迎友友们私信提问,家人们不要忘记点赞收藏+关注哦!!!
一、调整奇数偶数顺序
内容:输入一个整数数组,实现一个函数,来调整该数组中数字的顺序使得数组中所有的奇数位于数组的前半部分,所有偶数位于数组的后半部分。
1.不改变顺序
先讲一下思路:简单来讲就是遍历三次。展开来讲就是从左到右遍历一次寻找一次奇数存到新创建的数组里,再从左往右遍历一次找一次偶数放到那个新创建的数组里,最后再遍历把新的数组打印下来。代码如下:
//数组的奇数在前面,偶数在后面常规做法
#include<stdio.h>
void change(int arr[], int sz) {
int j = 0;
int arr2[1000] = { 0 };
int i = 0;
for (i = 0; i < sz; i++) { //先遍历第一次寻找奇数
if (arr[i] % 2 == 1) {
arr2[j] = arr[i];
j++;
}
}
for (i = 0; i < sz; i++) { //再遍历第二次寻找偶数
if (arr[i] % 2 == 0) {
arr2[j] = arr[i];
j++;
}
}
for (i = 0; i < sz; i++) { //遍历第三次打印
printf("%d ", arr2[i]);
}
}
int main() {
int arr[10] = { 1,3,2,4,7,5,6,9,8,10 };
int sz = sizeof(arr) / sizeof(arr[0]); //算出arr数组里元素的个数
change(arr, sz);
return 0;
}
2.改变顺序
思路为:二分查找,从数组左边往右走,数组右边往左走,当左边那个步子小于右边那个步子进入循环,左边找到的偶数跟右边找到的奇数进行交换,所以会改变原有的顺序。
大家伙可能有疑惑了,这怎么实现呢?其实很简单,进入一次循环就交换一次,直到循环条件不满足,退出函数。
//数组中奇数在前,偶数在后的二分查找做法
#include<stdio.h>
void change(int arr[], int sz) {
int left = 0;
int right = sz - 1;
int temp = 0;
while (left < right) { //进入循环条件是左比右小
if ((left<right) && (arr[left] % 2 == 1)) { //左端往右走寻找奇数,按兵不动
left++; //找到一个偶数,跳出if语句
}
if ((left<right) && (arr[right] % 2 == 0)) { //右端往左走寻找偶数,按兵不动
right--; //找到一个奇数,跳出if语句
}
temp = arr[left]; //寻找到了奇数和偶数。右端的奇数往左半部分放,左端的偶数往右半部分放
arr[left] = arr[right];
arr[right] = temp;
}
for (int i = 0; i < sz; i++) { //遍历一次,打印
printf("%d ", arr[i]);
}
}
int main() {
int arr[10] = { 1,3,2,4,7,5,6,9,8,10 };
int sz = sizeof(arr) / sizeof(arr[0]); //算出arr数组里元素的个数
change(arr, sz);
return 0;
}
二、合并两个有序数组
1.先合并再排序
基本思路:输入两个已经排序好的数组,将这两个数组放到新建立的数组里面,再进行这个数组的排序。
底下那个排序什么排序都可以,我这里用的是冒泡排序。
合并两个有序数列(简单做法)
#include<stdio.h>
void buller(int* arr, int sz) {
int j = 0;
int i = 0;
int temp = 0;
for (i = 0; i < sz - 1;i++) {
for (j = 0; j < sz - i - 1; j++) {
if (arr[j]> arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
for (j = 0; j < sz; j++) {
printf("%d ", arr[j]);
}
}
int main() {
int arr1[1000] = { 0 };
int arr2[1000] = { 0 };
int n = 0;
int m = 0;
int i = 0;
int arr3[2000] = { 0 };
int j = 0;
scanf("%d %d", &n, &m);
for (i = 0; i < n; i++) {
scanf("%d", &arr1[i]);
}
for (i = 0; i < m; i++) {
scanf("%d", &arr2[i]);
}
for (i = 0; i < n; i++) {
arr3[j] = arr1[i];
j++;
}
for (i = 0; i < m; i++) {
arr3[j] = arr2[i];
j++;
}
buller(arr3, n + m);
return 0;
}
2.数组比较排序
基本思路:
#include<stdio.h>
int main()
{
int n = 0;
int m = 0;
int arr1[1000] = { 0 };
int arr2[1000] = { 0 };
//输入n和m
scanf("%d %d", &n, &m); //n代表数组arr1[]的遍历条件,m表示数组arr2[]的遍历条件
int i = 0;
int j = 0;
//输入两个升序序列
for (i = 0; i < n; i++){
scanf("%d", &arr1[i]);
}
for (i = 0; i < m; i++){
scanf("%d", &arr2[i]);
}
//合并有序序列并输出
i = 0;
j = 0;//重新赋值为0
while (i < n && j < m) //进行数组的比较并输出(归并排序比较)
{
if (arr1[i] < arr2[j]){
printf("%d ", arr1[i]);
i++;
}
else{
printf("%d ", arr2[j]);
j++;
}
}
//判断尚未遍历完的数组是否需要打印输出
int count1 = 0;
int count2 = 0;
if (i == n && j < m) { //arr1[i]中的数组已经全部打印完成,剩下arr2[j]中尚未打印的数组
for (j = 0; j < m; j++) { //比较完以后数组arr1中的元素都排完了,还有arr2中的剩余元素需要求出来(在下面附上图片解释)
if (arr2[j] > arr1[n-1]) { //数组第一个元素是下标从0开始
count1++;
}
}
for (j = m - count1; j < m; j++) {
printf("%d ", arr2[j]);
}
}
else if( j == m && i < n ) { //arr2[j]中的数组已经全部打印完成,剩下arr1[i]中尚未打印的数组
for (i = 0; i < n; i++) {
if (arr1[i] > arr2[m-1]) {
count2++;
}
}
for (i = n - count2; i < n; i++) {
printf("%d ", arr1[i]);
}
}
return 0;
}
当数组arr1中的元素全部打印完成了以后,那自然多了数组arr2中的元素,此时,如何确定进入循环的初识值呢?这就需要一个比较的过程,引入一个count计数器,遍历数组arr2中的所有元素与数组arr1的最后一个(最大值)进行比较,如果大,count就往上加,这样还不是初始值,最后还要用元素总数减去这个count的值就为初始值。
三、判断有序数组
题目描述:输入一个整数序列,判断是否是有序序列,有序,指序列中的整数从小到大排序或者从大到小排序(相同元素也视为有序)。
基本思路:1.首先数组排序三种情况:降序,升序,大小一样,题目给的意思是相同元素也视为有序。
2.设置两个标杆flag1和flag2,分别赋原值为0,进入一个大的循环体里,遍历整个数组的元素个数并进行两个if语句判断,第一个if为升序,第二个if为降序,哪个满足令它的flag1或者flag2为1,一个数组里面有升序也有降序,最后判断的是flag1+flag2的大小,要是为1,说明这个数组里面既有降序也有升序,如果不为1或者干脆都为0,那么说明这个数组是个有序数组。
代码如下:
#include <stdio.h>
int main() {
int N = 0;
int i = 0;
int flag1 = 0;
int flag2 = 0; //给两个标识,用来判断这串数组
int arr[1000] = { 0 };
scanf("%d", &N);
for (i = 0; i < N; i++) {
scanf("%d", &arr[i]);
if (i > 0) {
//降序(判断是不是降序)
if (arr[i] < arr[i - 1]) {
flag1 = 1; //数组内部只要有相邻的两个元素是有序关系则flag赋值为1
}
//升序(判断是不是升序)
else if (arr[i] > arr[i - 1]) {
flag2 = 1; //数组内部只要有相邻的两个元素是有序关系则flag赋值为1
}
}
}
//flag都为1,则说明这个数组既有升序也有降序
if (flag1+flag2 == 2) {
printf("unsorted\n");
}
//只要有一个为1就成立
else {
printf("sorted\n");
}
return 0;
}
总结
对于第二天的刷题做个总结,这做的这三道题目确实有点难,很多细节要好好思考,好好斟酌,要不断提高自己的敲代码的能力,不要因为这个代码长,冗杂,就不敢去做它,要有耐心细心。