Data structure advanced training course notes and algorithm exercises

Source Code: https://github.com/MysticalGuest/DataStructure/tree/master/AdvancedJuniorTraining


题目1

荷兰国旗
现有n个红蓝白三种不同颜色的小球,乱序排列在一起;
请通过两两交换任意两个球,使得从左到右的球依次:红球、白球、蓝球

1.1 算法设计思想

把题目理解为这样的问题:
一个循环,把红色球和剩余的球交换,那么红球就排序好了,就是两两交换问题;
另一个循环,把剩下没排序好的白球和蓝球也排序好,也是两两交换;
程序的时间复杂度取决于长度取决于第一个循环,O(n)

1.2 源代码

#define RED 0
#define WHITE 1
#define BLUE 2

void swap(int *p, int *q){
  int temp;
  temp = *p;
  *p = *q;
  *q = temp;
}

void sort(int array[], int start, int end, int collor){
  int i=start, j=end;
  while(i < j){
    while(array[i]==collor){
      i++;
    }
    while(array[j]!=collor){
      j--;
    }
    swap(&array[i], &array[j]);
    i++;
  }
}

void main(){
  int ball[20]={1,2,2,0,1,0,1,2,0,0,0,1,2,1,0,1,2,0,0,1};
  int i, num_red=0;
  printf("There are 20 red, blue and white balls in three different colors, \ arranged together in disorder:\n");
  for(i=0; i<20; i++){
    if(ball[i]==RED){
      num_red++;
      printf("Red ");
    }
    if(ball[i]==WHITE)
      printf("White ");
    if(ball[i]==BLUE)
      printf("Blue ");
  }
  printf("\n");
  sort(ball, 0, 20, RED); // 把红色球排好序
  sort(ball, num_red, 20, WHITE); // 把白色球排好序
  printf("\nAfter sorting: \n");
  for(i=0; i<20; i++){
    if(ball[i]==RED)
      printf("Red ");
    if(ball[i]==WHITE)
      printf("White ");
    if(ball[i]==BLUE)
      printf("Blue ");
  }
  printf("\n");
}

1.3 运行情况截图



题目2

完美洗牌算法
有一个长度为2n的数组{a1,a2,a3,…an,b1,b2,b3, …bn},
希望“排序”后,变为{a1, b1, a2, b2, a3, b3,…an, bn}。
要求:尽可能高效。能否在时间复杂度为O(n),空间复杂度为O(1)的解法

2.1 算法设计思想

依次考察每个位置的变化规律
a1: 0 -> 不变
a2: 1 -> 2
a3: 2 -> 4
a4: 3 -> 6

an: n-1 -> 2n-2
b1: n -> 1
b2: n+1 -> 3
b3: n+2 -> 5

bn-1: 2n-2 -> 2n-3
bn: 2n-1 -> 不变
可以得出下标的变化规律:
j=(i * 2) % (n2 -1)
所以将值赋给辅助数组即可

2.2 源代码

void perfect_shuffle(char *a[],int n) {
  int n2 = n * 2, i, j;
  char *b[20];
  for (i = 1; i < n2-1; i++) {
    j=(i * 2) % (n2 -1);
    b[j] = a[i];
  }
  for (i = 1; i < n2-1; i++) {
    a[i] = b[i];
  }
}

2.3 运行情况截图



题目3

买票找零问题
在一场激烈的球赛开始之前,售票工作正在紧张地进行中,每张球票为50元。
现有2n个人排队购票,其中有n个人手持50元的钞票,
另外的n个人手持100元的钞票,假设开始售票时,售票处没有零钱。
要求:问这2n个人有多少种排队方式,不至于使售票处出现找不开钱的局面呢

3.1 算法设计思想

找规律递推的方法;
要求持50元n人,100元n人,多少种排队方式,那么排在最后的一定是持100元的人,所以和持50元n人,100元n-1人的排队方式相同;
发现规律,持50元n-1人,100元n-1人和持50元n-1人,100元n-2人的排队方式相同;
所以这就可以从最小的1开始求了,然后累加到n,得到最后结果

3.2 源代码

#define N 100

int arrange(int n){ 
  int array[N][N];
  int i, j;
  // 当100元和50元人数不相等,100元0人,则只有1中解决方案
  for(i=0; i<n; i++){
    array[i][0]=1;
  }
  // 若50元人数小于100元人数,则没有解决方案
  // 则二维数组的上三角的值都为0,不用初始化赋值
  // 开始递推,填满下三角矩阵数组
  for(i=1; i<=n; i++){
    for(j=0; j<=i; j++)
      array[i][j]=array[i-1][j]+array[i][j-1];
  }
  return array[n][n];
}

3.3 运行情况截图