Skip to content

Commit

Permalink
Update optimized solution
Browse files Browse the repository at this point in the history
  • Loading branch information
SomeBottle committed Nov 6, 2023
1 parent 3d24c1e commit 83bb010
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 1 deletion.
54 changes: 54 additions & 0 deletions Algo/code/C-Cpp/DataStructure/408-2010-OP.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include <cstdio>

using namespace std;

void Reverse(int *seq, int start, int end);

int main()
{
int seq[] = {1, 2, 3, 4, 5, 6, 7, 8};
int seqLen = sizeof(seq) / sizeof(seq[0]);
int p = 12; // 循环左移位数
// 以下是优解
p = p % seqLen; // (很重要!)可能会左移超过一个序列的长度,先模一下,得到实际要移动的位数。
Reverse(seq, 0, p - 1); // 逆置[0...p-1]子序列
Reverse(seq, p, seqLen - 1); // 逆置[p...n-1]子序列
Reverse(seq, 0, seqLen - 1); // 最后逆置整个序列
printf("Result: ");
for (int i = 0; i < seqLen; i++)
printf("%d ", seq[i]);
printf("\n");
return 0;
}

// 逆置子序列
void Reverse(int *seq, int start, int end)
{
int temp;
while (start < end)
{
temp = seq[start];
seq[start++] = seq[end];
seq[end--] = temp;
}
}

/*
这一题主要是一个线性表循环移位问题,把线性表循环左移p位。
这题可能被坑的地方就在于,需要考虑到循环移位次数超过序列长度的情况,需要把移动位数p模一下序列长度。
优解的方法非常巧妙,观察发现循环左移p位,其实通过在原地对子序列进行逆置(倒转)就能实现:
1. 逆置下标为[0...p-1]的子序列(设为序列A)
2. 逆置下标为[p...n-1]的子序列(设为序列B)
3. 逆置下标为[0...n-1]的序列
可以用分块矩阵来理解:
AB -> 分别逆置 (A^-1 B^-1) -> 整体逆置(A^-1 B^-1)^-1 = BA,正好就是循环移位的结果。
空间复杂度O(1)级别(原地操作),时间复杂度O(n)级别(Reverse算法为线性时间复杂度)
- SomeBottle 2023.11.6
*/
2 changes: 1 addition & 1 deletion Algo/code/C-Cpp/DataStructure/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
|:---:|:---:|:---:|:---:|:---:|
|Dotcpp-1713|[平衡二叉树的基本操作](https://www.dotcpp.com/oj/problem1713.html)|[AVLTree-Insertion.cpp](./AVLTree-Insertion.cpp)|| 主要考察**AVL**(二叉平衡搜索)树的**插入****查找**操作 |
|408-2009统考-42题|[求单链表倒数第k个数](https://zhuanlan.zhihu.com/p/575348442)|优解:[408-2009-OP.cpp](./408-2009-OP.cpp)| | 某种意义上是采用了滑动窗口的思想,实现是采用双指针法。 |
|408-2010统考-42题|[循环左移p位](https://zhuanlan.zhihu.com/p/574160078)|暴力解:[408-2010-BF.cpp](./408-2010-BF.cpp)| | 要考虑到循环左移超过一个序列长度的情况|
|408-2010统考-42题|[循环左移p位](https://zhuanlan.zhihu.com/p/574160078)|暴力解:[408-2010-BF.cpp](./408-2010-BF.cpp) 优解:[408-2010-OP.cpp](./408-2010-OP.cpp) | | 要考虑到**循环左移超过一个序列长度**的情况|
|408-2011统考-42题|[两等长有序序列的中位数](https://zhuanlan.zhihu.com/p/573721052)|暴力解:[408-2011-BF.cpp](./408-2011-BF.cpp)| | 两序列等长且有序,可以省掉不必要的边界条件判断。 |
|408-2012统考-42题|[寻找单链表共享部分](https://zhuanlan.zhihu.com/p/573074413)|暴力解:[408-2012-BF.cpp](./408-2012-BF.cpp)| | 直接两层循环暴扫。 |
|408-2013统考-41题|[寻找序列中出现次数超过一半的元素](https://zhuanlan.zhihu.com/p/572303218)|较优解:[408-2013-OP.cpp](./408-2013-OP.cpp)| | 哈希表直接定址,对数据出现次数进行统计。 |
Expand Down
2 changes: 2 additions & 0 deletions Algo/code/C-Cpp/PTA/DataStructure/DS-7-12.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <ctime>

using namespace std;

Expand All @@ -18,6 +19,7 @@ int Partition(Sequence &seq, int left, int right);

int main()
{
srand((unsigned int)time(NULL));
int N;
scanf(" %d", &N);
// 初始化数字序列
Expand Down

0 comments on commit 83bb010

Please sign in to comment.