算法題解

一、利用字符重複出現的次數,編寫一個方法,實現基本的字符串壓縮功能。數據結構

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<conio.h>
 4 #include <string.h>
 5 
 6 /*
 7 重複字符壓縮
 8 */
 9 void RepeatCharReduce(char *str, int n, char *s){
10 
11 //    char s[20];
12     char tmp = str[0];
13     s[0] = tmp;
14     int j = 1;
15     int count = 1;
16     for(int i = 1; i <n; i++){
17         if(str[i] == tmp){
18             count++;
19         }
20         else{
21             s[j] = count;
22             j++;
23             tmp = str[i];
24             s[j] = str[i];
25             count = 1;
26             j++;
27         }
28     }
29     s[j] = count;
30 
31 }
32 
33 int main(){
34     char str[] = "aabcccccaaa";
35     char s[20] = "0";
36     RepeatCharReduce(str, 11, s);
37     for(int j = 0; j < 11; j++){
38         printf("%c", str[j]);
39     }
40     printf("\n");
41     for(int i = 0; i < 11; i += 2){
42         printf("%c%d", s[i], s[i+1]);
43     }
44     printf("\n");
45     getch();
46     return 0;
47 }

 

二、給定一個字符串,要求把字符串前面的若干個字符移動到字符串的尾部,如把字符串「abcdef」前面的2個字符'a'和'b'移動到字符串的尾部,使得原字符串變成字符串「cdefab」。請寫一個函數完成此功能,要求對長度爲n的字符串操做的時間複雜度爲 O(n),空間複雜度爲 O(1)。ide

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<conio.h>
 4 #include<math.h>
 5 #include<time.h>
 6 #include <string.h>
 7 
 8 void ReverseString(char *s, int from, int to)
 9 {
10     while(from < to){
11     char t = s[from];
12     s[from++] = s[to];
13     s[to--] = t;
14     }
15 }
16 
17 void LeftRotateString(char *s, int n, int m)
18 {
19     m %= n;
20     ReverseString(s, 0, m-1);
21     ReverseString(s, m, n-1);
22     ReverseString(s, 0, n-1);
23 }
24 
25 int main(){
26     char s[] = "abcdefgh";
27     for(int i = 0; i < 8; i++){
28         printf("%c ", s[i]);
29     }
30     printf("\n");
31     LeftRotateString(s, 8, 3);
32     for(int i = 0; i < 8; i++){
33         printf("%c ", s[i]);
34     }
35     printf("\n");
36     getch();
37     return 0;
38 }

三、鏈表翻轉。給出一個鏈表和一個數k,好比,鏈表爲1→2→3→4→5→6,k=2,則翻轉後2→1→6→5→4→3,若k=3,翻轉後3→2→1→6→5→4,若k=4,翻轉後4→3→2→1→6→5,用程序實現。函數

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<conio.h>
  4 #include<math.h>
  5 #include<time.h>
  6 #include <string.h>
  7 
  8 #define OK 1
  9 #define ERROR 0
 10 #define TRUE 1
 11 #define FALSE 0
 12  
 13 #define MAXSIZE 20 /* 存儲空間初始分配量 */
 14  
 15 typedef int Status;/* Status是函數的類型,其值是函數結果狀態代碼,如OK等 */
 16 typedef int ElemType;/* ElemType類型根據實際狀況而定,這裏假設爲int */
 17 
 18  typedef struct Node{
 19      int data;
 20      struct Node *next;
 21 }Node, *LinkList;
 22 
 23 /* 初始化順序線性表 */
 24 Status InitList(LinkList *L)
 25 {
 26     *L=(LinkList)malloc(sizeof(Node)); /* 產生頭結點,並使L指向此頭結點 */
 27     if(!(*L)) /* 存儲分配失敗 */
 28     {
 29         return ERROR;
 30     }
 31     (*L)->next=NULL; /* 指針域爲空 */
 32     return OK;
 33 }
 34 
 35 
 36 /*  隨機產生n個元素的值,創建帶表頭結點的單鏈線性表L(頭插法) */
 37 void CreateListHead(LinkList *L, int n)
 38 {
 39     LinkList p;
 40     int i;
 41     srand(time(0));                         /* 初始化隨機數種子 */
 42     *L = (LinkList)malloc(sizeof(Node));
 43     (*L)->next = NULL;                      /*  先創建一個帶頭結點的單鏈表 */
 44     for (i=0; i < n; i++)
 45     {
 46         p = (LinkList)malloc(sizeof(Node)); /*  生成新結點 */
 47         p->data = rand()%100+1; /*  隨機生成100之內的數字 */
 48         printf("%d ", p->data);
 49         p->next = (*L)->next;
 50         (*L)->next = p;                      /*  插入到表頭 */
 51     }
 52 }
 53 /* 初始條件:順序線性表L已存在。操做結果:返回L中數據元素個數 */
 54 int ListLength(LinkList L)
 55 {
 56     int i=0;
 57     LinkList p=L->next; /* p指向第一個結點 */
 58     while(p)
 59     {
 60         i++;
 61         p=p->next;
 62     }
 63     return i;
 64 }
 65 Status visit(ElemType c)
 66 {
 67     printf("-> %d ",c);
 68     return OK;
 69 }
 70 /* 初始條件:順序線性表L已存在 */
 71 /* 操做結果:依次對L的每一個數據元素輸出 */
 72 Status ListTraverse(LinkList L)
 73 {
 74     LinkList p=L->next;
 75     while(p)
 76     {
 77         visit(p->data);
 78         p=p->next;
 79     }
 80     printf("\n");
 81     return OK;
 82 }
 83 
 84 LinkList ListReverse2(LinkList L)
 85 {
 86     LinkList current, p;
 87     if (L == NULL)
 88     {
 89         return NULL;
 90     }
 91     current = L->next;
 92     while (current->next != NULL)
 93     {
 94         p = current->next;
 95         current->next = p->next;
 96         p->next = L->next;
 97         L->next = p;
 98     }
 99     ListTraverse(L);
100     return L;
101 }
102 /*
103 一、鏈表翻轉。給出一個鏈表和一個數k,
104 好比,鏈表爲1→2→3→4→5→6,k=2,則翻轉後2→1→6→5→4→3,
105 若k=3,翻轉後3→2→1→6→5→4,
106 若k=4,翻轉後4→3→2→1→6→5,用程序實現。
107 
108 對於鏈表而言只是對指針的指向調換,因此不會耗費額外存儲空間,空間複雜度O(1)
109 時間複雜度此處看來也是線性的
110 */
111 
112 LinkList ReverseSpecArea(LinkList L, int k){
113     LinkList current, p, q;
114     LinkList temp;
115     int i = 1;
116     if (L == NULL)
117     {
118         return NULL;
119     }
120     current = L->next;
121 
122     while (current->next != NULL)
123     {
124         p = current->next;
125         current->next = p->next;
126         p->next = L->next;
127         L->next = p;
128         if(++i >= k){
129             break;
130         }
131     }//current始終指向起先除去頭結點的第一個元素
132     temp = current;
133     current = current->next;
134     while(current->next != NULL){
135         p = current->next;
136         current->next = p->next;
137         p->next = temp->next;
138         temp->next = p;
139     }
140     ListTraverse(L);
141 
142     return L;
143 }
144 
145  
146 void ReverseString(char *s, int from, int to)
147 {
148     while(from < to){
149     char t = s[from];
150     s[from++] = s[to];
151     s[to--] = t;
152     }
153 }
154 
155 void LeftRotateString(char *s, int n, int k)
156 {
157     k %= n;
158     ReverseString(s, 0, k-1);
159     ReverseString(s, k, n-1);
160 }
161 
162 int main(){
163     LinkList L;
164     LinkList h;
165     Status i;
166     int j,k,pos,value;
167     int length;
168     char opp;
169     ElemType e;
170     i=InitList(&L);
171     printf("%d\n", i);
172     
173     CreateListHead(&L,10);
174     printf("\n");
175     length = ListLength(L);
176     printf("%d\n", length);
177     printf("總體建立L的元素(頭插法):\n");
178     ListTraverse(L);
179     printf("\n");
180     h = L->next;
181     while(h){
182         printf("%d ", h->data);
183         h = h->next;
184     }
185     printf("\n");
186     ListReverse2(L);
187 //    printf("反轉指定位置3的元素\n");
188 //    ReverseSpecArea(L, 3);
189     printf("反轉指定位置5的元素\n");
190     ReverseSpecArea(L, 5);
191 
192     getch();
193     return 0;
194 }

 四、判斷一個棧是否是「迴文」(判斷一個字符串是否是迴文)spa

思路:將一個字符串依次所有入棧,而後再出棧,依次比較每一個字符是否相等,若存在一個不等即不是迴文,當所有相等時即爲迴文3d

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<conio.h>
  4 #include<math.h>
  5 #include<time.h>
  6 #include <string.h>
  7 
  8 typedef int Status;/* Status是函數的類型,其值是函數結果狀態代碼,如OK等 */
  9 typedef int ElemType;/* ElemType類型根據實際狀況而定,這裏假設爲int */
 10 typedef int SElemType;
 11 
 12 #define MAXSIZE 20
 13 #define OK 1
 14 #define ERROR 0
 15 #define TRUE 1
 16 #define FALSE 0
 17 //定義棧對象
 18 typedef struct{
 19     SElemType data[MAXSIZE];
 20     int top;//指示棧頂元素
 21 }SqStack;
 22 //初始化棧
 23 Status initStack(SqStack* S){
 24     S->top = -1;
 25     return OK;
 26 }
 27 Status visit(SElemType c)
 28 {
 29     printf("%d ",c);
 30     return OK;
 31 }
 32 /* 從棧底到棧頂依次對棧中每一個元素顯示 */
 33 Status StackTraverse(SqStack S)
 34 {
 35     int i;
 36     i=0;
 37     while(i<=S.top)
 38     {
 39         visit(S.data[i++]);
 40     }
 41     printf("\n");
 42     return OK;
 43 }
 44 //入棧
 45 Status push(SqStack* S, SElemType e){
 46     //首先判斷是否棧滿
 47     if(S->top == MAXSIZE - 1){
 48         return ERROR;
 49     }
 50     S->top++; /* 棧頂指針增長一 */
 51     S->data[S->top] = e;
 52     return OK;
 53 }
 54 /* 若棧不空,則刪除S的棧頂元素,用e返回其值,並返回OK;不然返回ERROR */
 55 Status Pop(SqStack *S,SElemType *e)
 56 {
 57     if(S->top==-1)//爲空
 58         return ERROR;
 59     *e=S->data[S->top];    /* 將要刪除的棧頂元素賦值給e */
 60     S->top--;                /* 棧頂指針減一 */
 61     return OK;
 62 }
 63 ElemType Pop1(SqStack *S)
 64 {
 65     if(S->top==-1)//爲空
 66         return ERROR;
 67     ElemType temp;
 68     temp = S->data[S->top];    /* 將要刪除的棧頂元素賦值給e */
 69     S->top--;                /* 棧頂指針減一 */
 70     return temp;
 71 }
 72 
 73 /* 若棧不空,則用e返回S的棧頂元素,並返回OK;不然返回ERROR */
 74 ElemType GetTop(SqStack S)
 75 {
 76     ElemType topElement;
 77     if (S.top==-1)
 78         return ERROR;
 79     else
 80         return S.data[S.top];
 81    
 82 }
 83 
 84 int main()
 85 {
 86     SqStack s1;
 87     SqStack s2;
 88     SqStack temps;
 89     bool flag = true;
 90     int opp = 0;
 91     int j;
 92     if(initStack(&s1)==OK && initStack(&s2)==OK && initStack(&temps)==OK)
 93     {
 94         printf("順序棧初始化成功。");
 95         StackTraverse(s1);
 96         StackTraverse(s2);
 97         StackTraverse(temps);
 98     }
 99     char* str = "asfdasegf";
100     char* str1 = "adfghgfda";
101     for(int i = 0; i < 9; i++){
102         push(&s1, str1[i]);
103         push(&temps, str1[i]);
104     }
105     StackTraverse(s1);
106     while((&temps)->top != -1){//不爲空
107         push(&s2, Pop1(&temps));
108     }
109     StackTraverse(s2);
110     while((&s1)->top != -1){
111         ElemType temp1 = Pop1(&s1);
112         ElemType temp2 = Pop1(&s2);
113         if(temp1 != temp2){
114             printf("temp1 = %d ", temp1);
115             printf("\n");
116             printf("temp2 = %d ", temp2);
117             printf("\n");
118             printf("不是迴文!");
119             flag = false;
120             break;
121         }
122     }
123     if(flag){
124         printf("是迴文!");
125     }    
126     getch();
127 }
View Code

 

此處採用的是順序棧的數據結構來實現的,也能夠採用鏈棧的結構處理指針

對於判斷一個字符串是不是迴文的問題能夠採用分別從字符串兩端遍歷的方式,逐個比較來斷定code

實現時需採用兩個指針變量分別指向頭和尾:front和rear對象

 1 bool IsPalindrome(const char *s, int n)
 2 {
 3     //非法輸入
 4     if (s == NULL || n < 1) 
 5         return false;   
 6     char *front, *back;
 7 
 8     //初始化頭指針和尾指針
 9     front = s; 
10     back = s + n - 1; 
11 
12     while (front < back) 
13     {
14         if (*front != *back)
15             return false; // 不是迴文,當即返回  
16         ++front;
17         --back;
18     }
19     return true; // 是迴文  
20 }
View Code

此方法效率較高,時間複雜度:O(n),空間複雜度:O(1)blog

固然,從中間向兩邊掃也是可行的:字符串

 1 bool IsPalindrome2(const char *s, int n)
 2 {
 3     if (s == NULL || n < 1) 
 4         return false; // 非法輸入  
 5     char *first, *second;
 6 
 7     int m = ((n >> 1) - 1) >= 0 ? (n >> 1) - 1 : 0; // m is themiddle point of s      右移一位至關於除以2
 8     first = s + m; 
 9     second = s + n - 1 - m;
10 
11     while (first >= s)
12     if (s[first--] != s[second++]) 
13         return false; // not equal, so it's not apalindrome  
14     return true; // check over, it's a palindrome  
15 }
View Code

時間複雜度:O(n),空間複雜度:O(1)

一、判斷一條單向鏈表是否是「迴文」

分析:對於單鏈表結構,能夠用兩個指針從兩端或者中間遍歷並判斷對應字符是否相等。但這裏的關鍵就是如何朝兩個方向遍歷。因爲單鏈表是單向的,因此要向兩個方向遍歷的話,能夠採起經典的快慢指針的方法,即先位到鏈表的中間位置,再將鏈表的後半逆置,最後用兩個指針同時從鏈表頭部和中間開始同時遍歷並比較便可。

後面會具體實現

相關文章
相關標籤/搜索