文章目錄
- 作業題積累
- 1判斷閏年
- 題目
- 答案
- 決議
- 2最大公約數和最小公倍數
- 題目
- 答案
- 決議
- 3分數求和
- 題目
- 答案
- 決議
- 4二分查找
- 題目
- 答案
- 決議
- 5字串逆序
- 題目
- 答案
- 決議
- 代碼邏輯
- 6進制轉換
- 題目
- 答案
- 決議
- 7冒泡排序
- 題目
- 答案
- 決議
- 8陣列操作
- 題目
- 答案
- 決議
- 9列印二進制奇數偶數位
- 題目
- 答案
- 決議
- 10交換兩個變數
- 題目
- 答案
- 決議
- 11統計二進制中1的個數
- 題目
- 答案
- 決議
- 12計算求和
- 題目
- 答案
- 決議
- 13自冪數
- 題目
- 答案
- 決議
- 14字串逆序
- 題目
- 答案
- 決議
- 15喝汽水問題
- 題目
- 答案
- 決議
- 16程式解釋
- 題目
- 答案
- 決議
- 17調整奇偶順序
- 題目
- 答案
- 決議
- 18楊輝三角
- 題目
- 答案
- 決議
- 19猜兇手
- 題目
- 答案
- 決議
- 20程式解釋
- 題目
- 答案
- 決議
- 21猜名次
- 題目
- 答案
- 決議
- 22楊氏矩陣
- 題目
- 答案
- 決議
- 23模擬`qsort`
- 題目
- 答案
- 決議
- 24字串左旋
- 題目
- 答案
- 決議
- 25檢查字串旋轉結果
- 題目
- 答案
- 決議
作業題積累
1判斷閏年
題目
判斷閏年函式,
答案
int main() {
int i = 0;
int leapyear = 0;
for (i = 1000; i <= 1900; i++) {
if ((i % 400 == 0) || (i % 4 == 0 && i % 100 != 0)) {
printf("%d ", i);
}
}
return 0;
}
int is_leap_year(int year) {
return (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0));
}
決議
閏年分為普通閏年和世紀閏年,其判斷方法為:
- 普通閏年:年份是4的倍數,且不是100的倍數,
y%4==0&&y%100!=0 - 世紀閏年:年份是整百數,且必須是400的倍數,
y%400==0
若將萬年內,設可整除4年的為 S A S_A SA?,可整除100年的為 S B S_B SB?,可整除400年的為 S C S_C SC?,

利用這張圖,閏年 S S S 可表示為 S A + S C S_A+S_C SA?+SC?,
四年一閏,百年不閏,四百年再閏,
2最大公約數和最小公倍數
題目
求出最大公因數和最小公倍數,
答案
//1.遍歷元素,暴力求解
int main() {
int num1 = 0;
int num2 = 0;
scanf("%d %d", &num1, &num2);
int min = num1 < num2 ? num1 : num2;
int max = num1 < num2 ? num2 : num1;
//遍歷元素
for (int i = min; i > 0; i--) {
if (num1 % i == 0 && num2 % i == 0) {
printf("%d", i);
break;
}
}
for(int i = max; i > 0; i++) {
if(i % num1 == 0 && i % num2 == 0) {
printf("%d\n", i);
break;
}
}
return 0;
}
//2.輾轉相除法
int main()
{
int a = 0;
int b = 0;
scanf("%d%d", &a, &b);
int tmp = a * b;
int c = 0;
while (c = a % b) {
a = b;
b = c;
}
//最大公約數
printf("%d\n", b);
//最小公倍數
printf("%d\n", tmp / b);
return 0;
}
//1.更相減損法
#include <math.h>
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
if (a % 2 == 0 && a > 2) {
a /= 2;
}
if (b % 2 == 0 && b > 2) {
b /= 2;
}
if (a < b) {
int tmp = a;
a = b;
b = tmp;
}
int tmp = a - b;
while (b != tmp) {
tmp = abs(tmp - b);
}
printf("%d\n", b);
return 0;
}
決議
- 最小公倍數比二者都大,最大公約數比二者都小,找最小公倍數則從二者中較大的向后遍歷,最大公約數是從最小值前前遍歷,
- 輾轉相除法
- 在二者之模不為0的情況下,除數賦給被除數,模賦給除數,再執行整數除法直至模為0時,除數為最大公約數,初始二者數值乘積除以最大公約數即為最小公倍數,
- 更相減損法
- 若二者能整除2則除,不可的話,那么用大數減去小數,互相減來減去,一直到減數與差相等為止,此時所得即最大公約數,
3分數求和
題目
計算1/1-1/2+1/3-1/4+1/5 …… + 1/99 - 1/100 的值,列印出結果,
答案
int main()
{
int num = 100;
double flg = 1.0;
double sum = 0;
for (int Den = 1; Den <= num; Den++) {
//1.
double pro = flg / (Den / 1.0);//小數能影響除法
//2.
double pro = flg / Den;
sum += pro;
flg = -flg;
}
printf("%lf\n", sum);
return 0;
}
決議
注意只有一個小數參與除法運算才可以觸發小數除法,故第二中直接把分子定義為浮點數,通過取負得到±1,
4二分查找
題目
二分查找,在一個有序整型陣列中查找某個數字,
答案
int main() {
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(arr)/sizeof(arr[0]);
int key = 0;
scanf("%d", &key);
int left = 0;
int right = sz - 1;
while(left <= right) {
int mid = (left + right) / 2;
if (arr[mid] > key) {
right = mid - 1;
}
else if (arr[mid] < key) {
left = mid + 1;
}
else {
printf("找到了下標為%d\n", mid);
}
}
if (left > right) {
printf("找不到\n");
}
return 0;
}
決議
通過下標訪問元素進行對比,從中間開始,臨界條件是左下標小于右下標,當然折半法僅限有序陣列,
5字串逆序
題目
撰寫一個函式 reverse(char* str),用遞回的方式實作:將引數字串中的字符反向排列,不是逆序列印,
要求:不能使用C函式庫中的字串操作函式,
例如:char arr[] = "abcdef";,逆序之后陣列內容變成:fedcba
答案
void reverse_string3(char* ch)//遞回
{
char* left = ch;
char* right = ch + strlen(ch) - 1;
if (*ch != '\0')
{
char tmp = *left;//提取
*left = *right;//賦值
*right = '\0';//賦\0
reverse_string3(ch+1);//ch+1,而不是ch++
*right = tmp;//賦值
}
}
決議
abcdef遞推:(先把后面賦值給前面,后面用覆寫\0)
$ \Rightarrow$
f b c d e \0? \Rightarrow ?
f e c \0\0? \Rightarrow ?
f e d \0\0\0回歸:(把前面轉移出去的字符對應賦值給\0)
$ \Rightarrow$
f e d c \0\0? \Rightarrow ?
f e d c b \0? \Rightarrow ?
f e d c b a

代碼邏輯
reverse(“abcdef\0”)
交換a和f+reverse(“f bcde\0\0”)
交換a和f+交換b和e+reverse(“fe cd\0\0\0”)
交換a和f+交換b和e+交換c和d+reverse(“fed \0\0\0\0”)
- 交換兩個字符
- 將在前的字符先放到一邊存著
- 把在后的字符賦值到前面的位置
- 再把后面的位置對應覆寫為
\0- 原在前字符替換
\0
- 把事先存好的在前的字符對應替換到
\0的位置上

6進制轉換
題目
將一個十進制數轉換成二進制并列印二進制序列的每一位,
答案
void Bin(n)
{
if (n / 2 != 0)
{
Bin(n / 2);
}
printf("%d", n % 2);
}
決議
10進制數轉換成二進制數,這是一個連續除2的程序:
- 把要轉換的數,除以2,得到商和余數,
- 將商繼續除以2,直到商為0,
最后將所有余數倒序排列,得到數就是轉換結果,
7冒泡排序
題目
有一個無序的整型陣列,使用冒泡排序的方法使其按升序或降序的方式排序,
答案
int BubbleSort() {
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int sz = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < sz - 1; i--) {
for (int j = 0; j < sz - 1 - i; j++) {
if (arr[j] < arr[j + 1]) {
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
決議

冒泡排序的核心思想是相鄰兩數相比,可以抽象為一個比較函式,
基本思路是比較 n ? 1 n-1 n?1 趟,每趟比較 n ? 1 ? i n-1-i n?1?i 次,
因為外回圈結束一次排序完一個數,使其來到其最終位置上,內回圈一次使其與未經和其比較的數進行比較,并在滿足條件的情況下進行交換,所以每次減
i,
8陣列操作
題目
實作reverse()函式完成陣列元素的逆置,
答案
void reverse(int arr[], int sz)
{
int left = 0;
int right = sz - 1;
while (left < right)
{
int tmp = arr[left];
arr[left] = arr[right];
arr[right] = tmp;
left++;
right--;
}
}
決議
通過下標訪問陣列元素從左向右依次進行交換,這種逆序整型陣列也可以逆序字串,都是一樣的字串也可以通過下標訪問,
9列印二進制奇數偶數位
題目
輸入一個整數,分別列印其二進制序列的奇數位和偶數位,
答案
int main() {
int n = 0;
int i = 0;
scanf("%d", &n);
printf("奇數位:");
for (i = 30; i >= 0; i -= 2) {
printf("%d ", (n >> i) & 1);
}
printf("\n偶數位:");
for (i = 31; i >= 1; i -= 2) {
printf("%d ", (n >> i) & 1);
}
return 0;
}
決議

回圈遍歷二進制序列中的每一位,讓每一位右移上i位都有機會來到最后一位和整數1按位與,這樣得到的數也只能1或0,這樣就相當于變相得到二進制序列的每一位,由于要區分奇數位和偶數位且按照順序列印,故要從后往前遍歷,
10交換兩個變數
題目
不創建臨時變數的條件下,交換兩個整型變數,
答案
int main()
{
int a = 10;
int b = 20;
printf("a=%d,b=%d\n", a, b);
//1.
a = a + b;
b = a - b;
a = a - b;
//2.
//(a^b)^a=b (a^b)^b=a
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("a=%d,b=%d\n", a, b);
return 0;
}
決議
不創建臨時變數來交換兩個整數資料,
- 通過賦值的方法,把
a+b賦值給a,此時a已經等于a+b,再將a-b賦值給b,這樣b就等于原來的a,再用a-b,這樣就得到了b再賦值給a,這樣a,b就完成了交換, - 通過按位異或的方法,按位異或的特點是,相同為0,相異為1,這樣就會導致一個結果
(a^b)^a=b,(a^b)^b=a,這樣的話把a^b的結果再與b異或然后賦值給b,再將a^b,也就是(a^b)^a=b賦值給a,
但二者都有局限,前者的大小受限,a+b加起來不可以大于一個整型不然就會溢位,后者因按位運算子僅是由于整型,故后者也受限于變數型別為整型,
11統計二進制中1的個數
題目
輸入一個整數,統計其二進制序列中1的個數,
答案
- 方法1
int Return_Number_1(int n)
{
int i = 0;
int count = 0;
for (i = 0; i < 32; i++)
{
if (((n >> i) & 1) == 1)
{
count++;
}
}
return count;
}
int main()
{
int n = 0;
scanf("%d", &n);
printf("%d\n", Return_Number_1(n));
return 0;
}
- 方法2
int main()
{
int n = 0;
int count = 0;
scanf("%d", &n);
while (n) {
n = n & (n - 1);
count++;
}
printf("%d\n", count);
return 0;
}

決議
如圖所示我們用n&(n-1)作為計數器的條件,可以發現n&(n-1)的結果比n的二進制序列少一個1,再將結果賦值給n,就可以依靠回圈來實作計數器,
12計算求和
題目
求 S n = a + a a + a a a + a a a a + a a a a a Sn = a + aa + aaa + aaaa + aaaaa Sn=a+aa+aaa+aaaa+aaaaa 的前5項之和,其中 a a a 是一個數字,例如: 2 + 22 + 222 + 2222 + 22222 2 + 22 + 222 + 2222 + 22222 2+22+222+2222+22222,
答案
第一種思路:
2 = 2*10^0
22 = 2*10^1 + 2
222 = 2*10^2 + 22
2222 = 2*10^3 + 222
22222 = 2*10^4 + 2222
22222 = 2*10^4 + 2222
第二種思路:
2 = 2 + 0
22 = 2 * 10 + 2
222 = 22 * 10 + 2
2222 = 222 * 10 + 2
22222 = 2222 * 10 + 2
#include <math.h>
int main()
{
int a = 0;
scanf("%d", &a);
int sum = 0;
int ret = 0;
for (int i = 0; i < 5; i++) {
//1.
ret += a * (int)pow(10, i);
//2.
ret = ret * 10 + a;
sum += ret;
}
printf("%d\n", sum);
return 0;
}
第三種方法:
#include <math.h>
int main()
{
int a = 0;
int n = 0;
int sum = 0;
scanf("%d %d", &a, &n);
while (n) {
int i = n;
int ite = 0;
while (i) {
ite += a * pow(10, i - 1);
i--;
}
sum += ite;
n--;
}
printf("%d\n", sum);
return 0;
}
決議
-
第一種是把 a a a 看作 a × 1 0 0 a×10^0 a×100, a a aa aa 看成 a × 1 0 1 + a × 1 0 0 a×10^1+a×10^0 a×101+a×100 ……
-
第二種每次在前一次運算的結果上乘10并加上2,
-
第三種是可以規定位數,
13自冪數
題目
求出0~100000之間的所有“水仙花數”并輸出,
“水仙花數”是指一個n位數,其各位數字的n次方之和確好等于該數本身,如:
153
=
1
3
+
5
3
+
3
3
153=1^3+5^3+3^3
153=13+53+33 ,
則153是一個“水仙花數”,
答案
#include<math.h>
int main() {
for (int i = 0; i < 10000; i++) {
//1. 求位數
int n = 1;
int num = i;
while (num /= 10) {
n++;
}
//2. 求每項和
int sum = 0;
num = i;
while (num) {
sum += (int)pow((num % 10), n);
num /= 10;
}
//3. 判斷
if (sum == i) {
printf("%d\n", i);
}
}
return 0;
}
決議
求自冪數需要三步,1求出該數的位數2求每項和3.判斷是否相等,每次做出改變i動作時,要把i賦值給臨時變數以免在回圈內改變臨時變數,
14字串逆序
題目
現有一字串i am a student,將其全部逆序得tneduts a ma i,
進階版:將其單詞外逆序,單詞內順序不變,得:student a am i,
答案
#include <string.h>
char* reverse(char* arr) {
int len = strlen(arr);
char* left = arr;
char* right = arr + len - 1;
while (left < right) {
char tmp = *left;
*left = *right;
*right = tmp;
left++;
right--;
}
return arr;
}
int main()
{
char arr[] = "i am a student";
reverse(arr);
printf("%s\n", arr);
return 0;
}
進階版:
char* reverse(char* left, char* right) {
while (left < right) {
char tmp = *left;
*left = *right;
*right = tmp;
left++;
right--;
}
return left;
}
char* move(char* arr) {
int len = strlen(arr);
reverse(arr, arr + len - 1);
reverse(arr, arr + 6);
reverse(arr + 8, arr + 8);
reverse(arr + 10, arr + 11);
reverse(arr + 13, arr + 13);
return arr;
}
//tneduts a ma i
//01234567890123
int main()
{
char arr[] = "i am a student";
move(arr);
printf("%s\n", arr);
return 0;
}
決議
把所有單詞都可視為字符,故逆序字串即可,進階版只需要將全部逆序后的結果數清每個字符的下標位置,并單獨在逆序就可以了,
15喝汽水問題
題目
喝汽水,1瓶汽水1元,2個空瓶可以換一瓶汽水,給20元,可以多少汽水,
答案
//喝汽水
int main()
{
int money = 20;
//買的
int total = money;
int empty = money;
//換的
while (empty > 1) {
total += empty / 2;
empty = empty / 2 + empty % 2;
}
printf("%d\n", total);
return 0;
}
決議
喝到的汽水可以分為兩種,一種是買來的一種是換來的,首先花已有的錢買來的一元一瓶故先total等于money,
然后計算換來的,定義空瓶數,兩個空瓶換一瓶,故total等于empty/2,empty執行整數除法,故empty等于不僅要/2還要%2,奇數瓶還會剩下奇數瓶,
16程式解釋
題目
請解釋下列代碼的運行結果和問題原因,
#include <stdio.h>
int main()
{
int i = 0;
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
for (i = 0; i <= 12; i++)
{
arr[i] = 0;
printf("hello bit\n");
}
return 0;
}
答案

決議
陣列其后第三塊空間正好被編譯器用來放置存盤下標的變數,故每次到這里都會清零,就重新開始了,每個編譯器的位置不一樣,這個屬于編譯器的自我優化,不是我們可以改變的,且在release版本會優化掉這個問題,
17調整奇偶順序
題目
調整陣列使奇數全部都位于偶數前面,
輸入一個整數陣列,調整該陣列中數字的順序,使得陣列中所有的奇數位于陣列的前半部分,所有偶數位于陣列的后半部分,
答案
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(arr) / sizeof(arr[0]);
int* pl = arr;
int* pr = &arr[sz - 1];
while (pl < pr) {
while (*pl % 2 == 1) {
pl++;
}
while (*pr % 2 == 0) {
pr--;
}
if (pl < pr) {
int tmp = *pl;
*pl = *pr;
*pr = tmp;
}
}
for (int i = 0; i < sz; i++) {
printf("%d ", arr[i]);
}
return 0;
}
決議
pl和pr不可以同時加減,在前面用pl尋找奇數,后面用pr尋找偶數,找到之后再兩者交換,
18楊輝三角
題目
列印如圖所示的資料三角形,
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
列印楊輝三角菱形形式,
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
答案
int main()
{
int n = 0;
scanf("%d", &n);
int arr[20][20] = { 0 };
arr[1][1] = 1;
for (int i = 2; i <= n; i++) {
for (int j = 1; j <= i; j++) {
arr[i][j] = arr[i - 1][j - 1] + arr[i - 1][j];//規律
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
進階版:
int main()
{
int arr[10][10] = { 0 };
for (int i = 0; i < 10; i++) {
for (int j = 0; j <= i; j++) {
//初始化
arr[i][0] = arr[i][i] = 1;
//計算
if (i >= 2 && j >= 1) {
arr[i][j] = arr[i - 1][j - 1] + arr[i - 1][j];
}
//列印
printf("%d ", arr[i][j]);
}
printf("\n");
}
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if (j < 9 - i) {
printf(" ");
}
else {
printf("%d ", arr[i][j - 9 + i]);
}
}
printf("\n");
}
return 0;
}
決議
首先楊輝三角的規律為 a r r [ i ] [ j ] = a r r [ i ? 1 ] [ j ? 1 ] + a r r [ i ? 1 ] [ j ] arr[i][j] = arr[i-1][j-1]+arr[i-1][j] arr[i][j]=arr[i?1][j?1]+arr[i?1][j] ,
- 第一種初始化時是從第2行第2列初始化,將arr[1][1]置為1,
- 第二種是將第1列和對角線初始化為1,然后從第3行第2列開始初始化,
19猜兇手
題目
日本某地發生了一件謀殺案,警察通過排查確定殺人兇手必為4個嫌疑犯的一個,以下為4個嫌疑犯的供詞:
A說:不是我,
B說:是C,
C說:是D,
D說:C在胡說
已知3個人說了真話,1個人說的是假話,
現在請根據這些資訊,寫一個程式來確定到底誰是兇手,
答案
int main()
{
int kill = 0;
//列舉法,一一列舉
for (kill = 'A'; kill <= 'D'; kill++) {
//利用運算式回傳值特點,直觀
if ((kill != 'A') +
(kill == 'C') +
(kill == 'D') +
(kill != 'D') == 3) {
printf("%c\n", kill);
break;
}
}
return 0;
}
決議
定義killer變數,將是與不是轉化為關于killer變數的關系運算,因為只有ABCD每人一個條件故只要一個回圈即可,三人真話,一人假話,故所有條件運算式相加的結果應為3,在killer假設條件正確時,
20程式解釋
題目
求代碼中strlen(a)的結果,并解釋清楚原因,
int main()
{
char a[1000] = { 0 };
int i = 0;
for (i = 0; i < 1000; i++)
{
a[i] = -1 - i;
}
printf("%d", strlen(a));
return 0;
}
答案
255
決議
求strlen(a)的值,也就是求a[i]=0的時候,i為多少,準確的來說應該是-1-i等于多少,因為陣列a為字符元素陣列,故當-1-i的尾七位二進制補碼為全1的時候,由于存入陣列時發生截斷故存入的是0,
21猜名次
題目
5位運動員參加了10米臺跳水比賽,有人讓他們預測比賽結果:
A選手說:B第二,我第三;
B選手說:我第二,E第四;
C選手說:我第一,D第二;
D選手說:C最后,我第三;
E選手說:我第四,A第一;
比賽結束后,每位選手都說對了一半,請編程確定比賽的名次,
答案
int main()
{
int a = 0;
int b = 0;
int c = 0;
int d = 0;
int e = 0;
for (a = 1; a <= 5; a++) {
for (b = 1; b <= 5; b++) {
for (c = 1; c <= 5; c++) {
for (d = 1; d <= 5; d++) {
for (e = 1; e <= 5; e++) {
//回圈5^5次
//判斷條件1.
//if ((b == 2) + (a == 3) +
// (b == 2) + (e == 4) +
// (c == 1) + (d == 2) +
// (c == 5) + (d == 3) +
// (e == 4) + (a == 1) == 5) {
//判斷條件2.
if (((b == 2) + (a == 3) == 1) &&
((b == 2) + (e == 4) == 1) &&
((c == 1) + (d == 2) == 1) &&
((c == 5) + (d == 3) == 1) &&
((e == 4) + (a == 1) == 1)) {
if (a * b * c * d * e == 120) {//1*2*3*4*5=120
printf("a=%d,b=%d,c=%d,d=%d,e=%d\n", a, b, c, d, e);
goto again;
return 0;
}
}
}
}
}
}
}
again:
}
決議
找兇手的題目兇手只有一個,猜名次必須要排序,所以要有5個回圈,每個回圈判斷一個選手的名次,同樣是把所有人的話作為一個條件,限制條件是每個人只有半句是對的,所以是兩個條件加起來是1,最后要取出排名重復的情況,
22楊氏矩陣
題目
有一個數字矩陣,矩陣的每行從左到右是遞增的,矩陣從上到下是遞增的,
請撰寫程式在這樣的矩陣中查找某個數字是否存在,
要求:時間復雜度小于O(N);
答案
void find_key(int(*pa)[3], int* px, int* py, int k) {
int x = *px;
int y = *py;
while (x < 3 && y >= 0) {
if (pa[x][y] > k) {
y--;
}
else if (pa[x][y] < k) {
x++;
}
else {
printf("(%d,%d)\n", x, y);
return;
}
}
printf("NO\n");
}
int main() {
int arr[3][3] = { {1,2,3},{4,5,6},{7,8,9} };
int key = 7;
int x = 0;
int y = 2;
find_key(arr, &x, &y, key);
return 0;
}
決議
因為所謂楊氏矩陣的定義就是該矩陣從左向右遞增從上到下遞增,不一定是按照某種順序,同時要求時間復雜度不超過 O ( N = n 2 ) O(N=n^2) O(N=n2),所以不可以遍歷,所以從矩陣的特點入手,從矩陣的右上角入手,該數字是該行的最大值,又是該列的最小值,這樣就可以通過大小比較來控制行和列,
23模擬qsort
題目
模擬實作my_qsort函式,并排序整型陣列,
答案
//列印函式
Print(int* arr, int sz) {
for (int i = 0; i < sz; i++) {
printf("%d ", arr[i]);
}
putchar(10);
}
//比較函式
int cmp(const void* e1, const void* e2) {
return *(int*)e1 - *(int*)e2;
}
//交換函式
void Swap(char* buf1, char* buf2, size_t width) {
for (size_t i = 0; i < width; i++) {
char tmp = *(buf1 + i);
*(buf1 + i) = *(buf2 + i);
*(buf2 + i) = tmp;
}
}
//模擬實作qsort
void my_qsort(void* base, size_t num, size_t width, int(*cmp)(const void*, const void*)) {
for (size_t i = 0; i < num; i++) {
for (size_t j = 0; j < num - i - 1; j++) {
if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0) {
Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
}
}
}
}
int main() {
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
int sz = sizeof(arr) / sizeof(arr[0]);
my_qsort(arr, sz, sizeof(arr[0]), cmp);
Print(arr, sz);
return 0;
}
決議
排序函式的要素:起始位置,元素大小,元素寬度以及比較函式,比較函式中要內嵌交換函式,
24字串左旋
題目
實作一個函式,可以左旋字串中的k個字符,
例如:ABCD左旋一個字符得到BCDA,ABCD左旋兩個字符得到CDAB,
答案
- 第一種方案
#include <string.h>
#include <assert.h>
char* left_hand(char* arr, int k) {
assert(arr);
int len = strlen(arr);
//0. 判斷次數
k %= len;
while (k) {
//1. 提取第一個字符
char tmp = arr[0];
//2. 后面的字符向前移動一位
for (int i = 1; i < len; i++) {
arr[i - 1] = arr[i];
}
//3. 插入最后一個字符
arr[len - 1] = tmp;
k--;
}
//4. 回傳字串地址
return arr;
}
int main() {
char arr[] = "ABCD";
int k = 2;
printf("%s\n", left_hand(arr, k));
return 0;
}
- 第二種方案
//AB CDEF
//BA FECD
//CD EFAB
char* reverse(char* left,char* right) {
char* begin = left;
while (left <= right) {
char tmp = *left;
*left = *right;
*right = tmp;
left++;
right--;
}
return begin;
}
char* hand(char* arr, int k) {
int len = strlen(arr);
reverse(arr, arr + k - 1);
reverse(arr + k, arr + len - 1);
reverse(arr, arr + len - 1);
}
int main()
{
char arr[] = "ABCDEF";
int k = 2;
hand(arr, k);
printf("%s\n", arr);
return 0;
}
決議
- 第一種是每次左旋一個字符,再回圈k次,左旋的邏輯是提取字符然后剩余元素前移一位最后字符放入最后位置,
- 第二種是確定左旋字符個數后,先分別逆序前后兩個字串,再將整個字串逆序,
25檢查字串旋轉結果
題目
寫一個函式,判斷一個字串是否為另外一個字串旋轉之后的字串,
例如:給定s1 = AABCD和s2 = BCDAA,回傳1;給定s1 = ABCD和s2 = ACBD,回傳0,
AABCD左旋一個字符得到ABCDA
AABCD左旋兩個字符得到BCDAA
AABCD右旋一個字符得到DAABC
答案
- 第一種方案
#include <string.h>
#include <assert.h>
int check_hand(char* s1, char* s2) {
assert(s1 && s2);
int len1 = strlen(s1);
int len2 = strlen(s2);
if (len1 != len2) {
return 0;
}
else {
for (int k = 0; k < len2; k++) {
if (strcmp(left_hand(s1, 1), s2) == 0) {
return 1;
}
}
return 0;
}
}
int main()
{
char s1[] = "AABCD";
char s2[] = "DAABC";
int ret = check_hand(s1, s2);
printf("%d\n", ret);
return 0;
}
- 第二種方案
#include <string.h>
int check_by_add(char* s1, char* s2) {
assert(s1 && s2);
int len = strlen(s1);
char* ps = strncat(s1, s1, len);
if ((size_t)len != strlen(ps)) {
return 0;
}
else {
if (strstr(ps, s1)) {
return 1;
}
else
return 0;
}
}
//AABCD AABCD
int main()
{
char s1[20] = "AABCD";
char s2[20] = "DAABC";
if (check_by_add(s1, s2)) {
printf("Yes\n");
}
else {
printf("No\n");
}
return 0;
}
決議
-
第一種是將需判斷字串與源字串所有旋轉的結果進行比較,同樣右旋k個字符也就等于左旋n-k個字符,
-
第二種是字串最后追加一個源字串,這樣任意旋轉后的結果字串必然是該字串的子字串,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/300292.html
標籤:其他
