当前位置:   article > 正文

算法回忆录(2)

算法回忆录(2)

6.输入一个非递减排列的整数数组nums,和一个目标值target。请找出给定目标值在数组中的开始位置和结束位置。 如果数组中不存在目标值target,则输出0,0。请设计一个时间复杂度为0(log n)的算法解决此问题。

输入包括两行,第一行输入两个整数,分别表示数组的长度和target,第二行输入数组nums。输出为一个整数。

例如输入:

6 8

5 7 7 8 8 10

则输出: 4 5

若输入:

6 9

5 7 7 8 8 10

则输出: 0 0

  1. #include <stdio.h>
  2. // 二分查找的变种,用于找到目标值的左边界
  3. int findLeftBound(int* nums, int numsSize, int target) {
  4. int left = 0, right = numsSize - 1;
  5. int leftBound = -1; // 初始化左边界为-1,表示未找到
  6. while (left <= right) {
  7. int mid = left + (right - left) / 2;
  8. if (nums[mid] >= target) {
  9. right = mid - 1; // 尝试在左半部分查找
  10. leftBound = mid; // 更新左边界
  11. } else {
  12. left = mid + 1;
  13. }
  14. }
  15. return leftBound;
  16. }
  17. // 二分查找的变种,用于找到目标值的右边界
  18. int findRightBound(int* nums, int numsSize, int target) {
  19. int left = 0, right = numsSize - 1;
  20. int rightBound = -1; // 初始化右边界为-1,表示未找到
  21. while (left <= right) {
  22. int mid = left + (right - left) / 2;
  23. if (nums[mid] <= target) {
  24. left = mid + 1; // 尝试在右半部分查找
  25. rightBound = mid; // 更新右边界
  26. } else {
  27. right = mid - 1;
  28. }
  29. }
  30. return rightBound;
  31. }
  32. int main() {
  33. int numsSize, target;
  34. scanf("%d %d", &numsSize, &target);
  35. int nums[numsSize];
  36. for (int i = 0; i < numsSize; i++) {
  37. scanf("%d", &nums[i]);
  38. }
  39. int leftBound = findLeftBound(nums, numsSize, target);
  40. int rightBound = findRightBound(nums, numsSize, target);
  41. // 如果左边界仍为-1,说明未找到目标值
  42. if (leftBound == -1) {
  43. printf("0 0\n");
  44. } else {
  45. printf("%d %d\n", leftBound + 1, rightBound + 1); // 数组索引从0开始,输出从1开始
  46. }
  47. return 0;
  48. }

解释和步骤:

  1. 函数 findStartIndex

    • 使用修改版的二分查找来找到目标值在数组中的起始位置。
    • 初始化左右边界,然后在循环中根据中间元素与目标值的比较调整左右边界。
    • 如果找到目标值,更新 start 并继续向左查找。
  2. 函数 findEndIndex

    • 使用同样的修改版二分查找来找到目标值在数组中的结束位置。
    • 初始化左右边界,然后在循环中根据中间元素与目标值的比较调整左右边界。
    • 如果找到目标值,更新 end 并继续向右查找。
  3. 主函数 main

    • 输入数组的长度和目标值。
    • 输入排序后的整数数组。
    • 调用 findStartIndexfindEndIndex 函数找到目标值的起始位置和结束位置。
    • 如果找到了起始位置和结束位置,则输出它们;否则输出 "0 0" 表示目标值不存在于数组中。

运行结果:

7. 残缺棋盘是一个有2k×2k (k≥1)个方格的棋盘,其中恰有一个方格残缺。 下图给出k=1时各种可能的残缺棋盘,其中残缺的方格用阴影表示。

图中的棋盘称作“三格板”,残缺棋盘问题就是用这四种三格板覆盖更大的残缺棋盘。在覆盖中要求: 1)两个三格板不能重叠 2)三格板不能覆盖残缺方格,但必须覆盖其他所有方格 编程输入k及残缺格的坐标,求残缺棋盘覆盖方法。 输入:三个整数,分别表示k值和残缺格的坐标; 输出:2k×2k矩阵,具体数值为覆盖的序号。

  1. #include<stdio.h>
  2. #include<math.h>
  3. void TileBoard(int tr,int tc,int dr,int dc,int size);
  4. void OutputBoard(int size);
  5. int tile=1;
  6. int Board[1025][1025];
  7. int main()
  8. {
  9. int n,a,b;
  10. scanf("%d",&n);
  11. int sum;
  12. sum=pow(2,n);
  13. scanf("%d %d",&a,&b);
  14. Board[n][n]=0;
  15. TileBoard(0,0,a,b,sum);
  16. OutputBoard(sum);
  17. return 0;
  18. }
  19. void TileBoard(int tr,int tc,int dr,int dc,int size)
  20. {
  21. if(size==1) return;
  22. int t=tile++,
  23. s=size/2;
  24. if(dr<tr+s&&dc<tc+s)
  25. TileBoard(tr,tc,dr,dc,s);
  26. else
  27. {
  28. Board[tr+s-1][tc+s-1]=t;
  29. TileBoard(tr,tc,tr+s-1,tc+s-1,s);
  30. }
  31. if(dr<tr+s&&dc>=tc+s)
  32. TileBoard(tr,tc+s,dr,dc,s);
  33. else
  34. {
  35. Board[tr+s-1][tc+s]=t;
  36. TileBoard(tr,tc+s,tr+s-1,tc+s,s);
  37. }
  38. if(dr>=tr+s&&dc<tc+s)
  39. TileBoard(tr+s,tc,dr,dc,s);
  40. else
  41. {
  42. Board[tr+s][tc+s-1]=t;
  43. TileBoard(tr+s,tc,tr+s,tc+s-1,s);
  44. }
  45. if(dr>=tr+s&&dc>=tc+s)
  46. TileBoard(tr+s,tc+s,dr,dc,s);
  47. else
  48. {
  49. Board[tr+s][tc+s]=t;
  50. TileBoard(tr+s,tc+s,tr+s,tc+s,s);
  51. }
  52. }
  53. void OutputBoard(int size)
  54. {
  55. for(int i=0;i<size;i++)
  56. {
  57. for(int j=0;j<size;j++){
  58. printf("%-3d",Board[i][j]);
  59. }
  60. printf("\n");
  61. }
  62. printf("end");
  63. }

 运行结果:

8. 活动安排问题求解: 假设某社团某一天要组织n个活动E={1,2,3...n},其中每个活动都要求使用同一礼堂,而且在同一时间内只有一个活动能使用这个礼堂。每个活动i都有一个要求使用礼堂的起始时间si和结束时间fi, 且有si<fi,。若区间(si,fi,)和(sj,fj,)不相交,则称活动i与活动j是相容的。

现在给定n个活动的开始时间和结束时间,请设计一个活动安排方案,使得安排的相容活动数目最多。

表1 活动时间表

1

2

3

4

5

6

7

8

10

11

12

1

2

0

5

3

5

6

8

2

12

15

3

4

5

7

8

9

10

11

13

14

18

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. // 定义活动结构体,包含活动的索引、开始时间和结束时间
  4. struct Activity {
  5. int index; // 活动的索引或编号
  6. int start; // 活动的开始时间
  7. int end; // 活动的结束时间
  8. };
  9. // 比较函数,用于qsort,根据活动的结束时间进行排序
  10. // 返回值小于0表示a小于b,大于0表示a大于b,等于0表示a等于b
  11. int compare(const void *a, const void *b) {
  12. struct Activity *activityA = (struct Activity *)a; // 将void指针转换为Activity指针
  13. struct Activity *activityB = (struct Activity *)b; // 将void指针转换为Activity指针
  14. return (activityA->end - activityB->end); // 返回两个活动结束时间的差值
  15. }
  16. int main() {
  17. int n = 12; // 活动的总数
  18. // 初始化活动数组
  19. struct Activity activities[] = {
  20. {1, 1, 3},
  21. {2, 12, 14},
  22. {3, 0, 5},
  23. {4, 5, 7},
  24. {5, 6, 10},
  25. {6, 3, 8},
  26. {7, 8, 12},
  27. {8, 5, 9},
  28. {9, 8, 11},
  29. {10, 2, 13},
  30. {11, 2, 4},
  31. {12, 15, 18}
  32. };
  33. // 使用qsort函数对活动数组进行排序,根据活动的结束时间
  34. qsort(activities, n, sizeof(struct Activity), compare);
  35. // 初始化计数器,用于记录被安排的活动数量
  36. int counter = 1; // 至少可以安排一个活动
  37. // 初始化最后一个已安排活动的结束时间
  38. int last_end_time = activities[0].end; // 第一个活动的结束时间
  39. // 打印第一个被安排的活动
  40. printf("第%d个活动被安排: %d开始, %d结束.\n", activities[0].index, activities[0].start, activities[0].end);
  41. // 遍历剩余的活动,尝试安排它们
  42. for (int i = 1; i < n; i++) {
  43. // 如果当前活动的开始时间不小于上一个已安排活动的结束时间,则可以安排
  44. if (activities[i].start >= last_end_time) {
  45. counter++; // 增加计数器
  46. printf("第%d个活动被安排: %d开始, %d结束.\n", activities[i].index, activities[i].start, activities[i].end);
  47. // 更新最后一个已安排活动的结束时间
  48. last_end_time = activities[i].end;
  49. }
  50. }
  51. // 打印总计被安排的活动数量
  52. printf("总计%d个活动被安排\n", counter);
  53. return 0;
  54. }

运行结果:

9. 设有n个独立的作业{1,2…,n},由m台相同的机器进行加工处理。作业i所需时间为Ti。约定任何作业可以在任何一台机器上加工处理,但未完工前不允许中断处理,任何作业不能拆分成更小的子作业。要求给出一种作业调度方案,使所给的n个作业在尽可能短的时间内由m台机器加工处理完成。输入第一行输入n和m;第二行输入n个整数,分别表示n个作业做需要的时间,输出结果为一个整数,表示完成任务的最短时间。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. // 比较函数,用于排序作业
  4. int compare(const void *a, const void *b) {
  5. return (*(int*)b - *(int*)a);
  6. }
  7. // 计算完成任务的最短时间
  8. int shortestCompletionTime(int n, int m, int jobs[]) {
  9. // 按处理时间从大到小排序作业
  10. qsort(jobs, n, sizeof(int), compare);
  11. // 初始化每台机器的当前总处理时间为0
  12. int machines[m];
  13. for (int i = 0; i < m; i++) {
  14. machines[i] = 0;
  15. }
  16. // 将作业分配给机器
  17. for (int i = 0; i < n; i++) {
  18. // 找到当前处理时间最短的机器
  19. int minIndex = 0;
  20. for (int j = 1; j < m; j++) {
  21. if (machines[j] < machines[minIndex]) {
  22. minIndex = j;
  23. }
  24. }
  25. // 分配作业给当前处理时间最短的机器,并更新其总处理时间
  26. machines[minIndex] += jobs[i];
  27. }
  28. // 找到所有机器中总处理时间最长的时间
  29. int maxTime = machines[0];
  30. for (int i = 1; i < m; i++) {
  31. if (machines[i] > maxTime) {
  32. maxTime = machines[i];
  33. }
  34. }
  35. return maxTime;
  36. }
  37. int main() {
  38. int n, m;
  39. scanf("%d %d", &n, &m);
  40. int jobs[n];
  41. for (int i = 0; i < n; i++) {
  42. scanf("%d", &jobs[i]);
  43. }
  44. // 计算并输出完成任务的最短时间
  45. int shortestTime = shortestCompletionTime(n, m, jobs);
  46. printf("%d", shortestTime);
  47. return 0;
  48. }

运行结果:

10. n个孩子站成一排。输入一个整数数组 ratings 表示每个孩子的评分。你需要按照以下要求,给这些孩子分发苹果:每个孩子至少分配到1个苹果。相邻两个孩子评分更高的孩子会获得更多的苹果。请你给每个孩子分发苹果,计算并返回需要准备的最少苹果数目。

  1. #include <stdio.h>
  2. int minApples(int ratings[], int n) {
  3. if (n <= 0) return 0;
  4. int apples[n];
  5. for (int i = 0; i < n; ++i) apples[i] = 1; // 每个孩子至少分配一个苹果
  6. // 从左向右扫描,保证右边评分高的孩子拿到的苹果比左边多
  7. for (int i = 1; i < n; ++i) {
  8. if (ratings[i] > ratings[i - 1]) {
  9. apples[i] = apples[i - 1] + 1;
  10. }
  11. }
  12. // 从右向左扫描,保证左边评分高的孩子拿到的苹果比右边多
  13. for (int i = n - 2; i >= 0; --i) {
  14. if (ratings[i] > ratings[i + 1] && apples[i] <= apples[i + 1]) {
  15. apples[i] = apples[i + 1] + 1;
  16. }
  17. }
  18. int totalApples = 0;
  19. for (int i = 0; i < n; ++i) {
  20. totalApples += apples[i];
  21. }
  22. return totalApples;
  23. }
  24. int main() {
  25. int n;
  26. scanf("%d", &n);
  27. int ratings[n];
  28. for (int i = 0; i < n; ++i) {
  29. scanf("%d", &ratings[i]);
  30. }
  31. int minTotalApples = minApples(ratings, n);
  32. printf("%d", minTotalApples);
  33. return 0;
  34. }

运行结果:

 结语

宝剑锋从磨砺出

梅花香自苦寒来

!!!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/在线问答5/article/detail/934257
推荐阅读
相关标签
  

闽ICP备14008679号