├── .gitignore ├── .vscode └── launch.json ├── ADT_cpp ├── Binary_Tree.cpp ├── Coputational_Geometry.cpp └── LinkList_demo.cpp ├── ADT_py ├── Deque.py ├── Queue.py ├── Stack.py ├── __init__.py └── __pycache__ │ ├── Stack.cpython-36.pyc │ └── __init__.cpython-36.pyc ├── CH1_Stack_Queue ├── $ ├── 10_Max_Min_Num.cpp ├── 11_Mountain_Num.cpp ├── 1_getMin.cpp ├── 1_getMin.py ├── 1_getMin_class.cpp ├── 2_stack_queue.cpp ├── 3_Inverse_Stack_by_Recursion.cpp ├── 3_Inverse_Stack_by_Recursion.py ├── 4_Dog_Cat_Queue.cpp ├── 5_Sort_Stack.cpp ├── 6a_Hanoi_Recursive.cpp ├── 7_Max_Windows_Array.cpp ├── 8a1_Monotate_Stack.cpp ├── 8a2_Monotate_Stack.cpp ├── 8b_Monotate_Stack.cpp ├── 9_Max_SubMatrix.cpp ├── Draft_8c_Monotate_Stack.cpp ├── ans.txt ├── in.txt └── out.txt ├── CH2_LinkedList ├── 10a_Add_2LinkedList.cpp ├── 10b_Add_2LinkedList.cpp ├── 12a_Reverse_KNode.cpp ├── 12b_Reverse_KNode.cpp ├── 13a_Delete_Repeat_node.cpp ├── 13b_Delete_Repeat_node.cpp ├── 14_Delete_Specify_node.cpp ├── 15a_Tree_List.cpp ├── 15b_Tree_List.cpp ├── 16_Selection_Sort.cpp ├── 17_Delete_tempnode.cpp ├── 18_Circular_List_Insert.cpp ├── 19_Merge_2List.cpp ├── 1_Overlap_List.cpp ├── 20_Left_RightMerge.cpp ├── 2_Delete_Lastk.cpp ├── 3_Delete_Medium.cpp ├── 4_Reverse_LinkedList.cpp ├── 5_Reverse_SubLinkedList.cpp ├── 6a_Joseph.cpp ├── 6b_Joseph.cpp ├── 7a1_Palindrome.cpp ├── 7a2_Palindrome.cpp ├── 7b_Palindrome.cpp ├── 8a_Partition.cpp ├── 8b_Partition.cpp ├── 8b_Partition.py ├── 9a_Random_LinkedList.cpp ├── 9b_Random_LinkedList.cpp ├── ans.txt ├── in.txt └── out.txt ├── CH3_Binary_Tree ├── .idea │ ├── CH3_Binary_Tree.iml │ ├── inspectionProfiles │ │ └── profiles_settings.xml │ ├── misc.xml │ ├── modules.xml │ ├── vcs.xml │ └── workspace.xml ├── 1a_Traverse_Recursive.cpp ├── 2_Print_Edge_Node.cpp ├── 3a_Sequence_Inverse.cpp ├── 4_serialization.cpp ├── 6_max_path_len.cpp ├── ans.txt ├── in.txt └── out.txt ├── CH8_Array_Matrix ├── 10_max_subarray_len_pos_element.cpp └── in.txt ├── Cover.jpg ├── Debug ├── Debug.cbp ├── Debug.depend ├── Debug.layout ├── debug.cpp ├── in.txt └── main.cpp └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // 使用 IntelliSense 了解相关属性。 3 | // 悬停以查看现有属性的描述。 4 | // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "(gdb) 启动", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "输入程序名称,例如 ${workspaceFolder}/a.exe", 12 | "args": [], 13 | "stopAtEntry": false, 14 | "cwd": "${workspaceFolder}", 15 | "environment": [], 16 | "externalConsole": false, 17 | "MIMode": "gdb", 18 | "miDebuggerPath": "/path/to/gdb", 19 | "setupCommands": [ 20 | { 21 | "description": "为 gdb 启用整齐打印", 22 | "text": "-enable-pretty-printing", 23 | "ignoreFailures": true 24 | } 25 | ] 26 | } 27 | ] 28 | } -------------------------------------------------------------------------------- /ADT_cpp/Binary_Tree.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-12.1 3 | 二叉树模板 4 | */ 5 | 6 | #include 7 | using namespace std; 8 | 9 | struct Node 10 | { 11 | int val; 12 | Node *left, *right; 13 | }; 14 | 15 | Node* Construct() // 构造二叉树 16 | { 17 | int n, root_ind; 18 | cin >> n >> root_ind; 19 | Node *node = new Node[n+1]; // 注意默认构造函数问题! 20 | int fa, lch, rch; 21 | for (int i = 1; i <= n; i++) 22 | { 23 | cin >> fa >> lch >> rch; 24 | node[fa].val = fa; 25 | node[fa].left = lch!=0 ? &node[lch] : NULL; // 是0则为NULL,否则指向lch的地址 26 | node[fa].right = rch!=0 ? &node[rch] : NULL; 27 | } 28 | return &node[root_ind]; // 返回指针 29 | } 30 | 31 | 32 | void PreOrder(Node* root) // 先序:中左右 33 | { 34 | if (root == NULL) 35 | return ; 36 | cout << root->val << " "; 37 | PreOrder(root->left); 38 | PreOrder(root->right); 39 | } 40 | 41 | 42 | int main() 43 | { 44 | Node *root = Construct(); // 构建二叉树 45 | PreOrder(root); 46 | cout << endl; 47 | 48 | return 0; 49 | } 50 | 51 | -------------------------------------------------------------------------------- /ADT_cpp/Coputational_Geometry.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-10.23 3 | 计算几何模板 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | class Point // 点类 12 | { 13 | public: 14 | double x, y; 15 | Point(double xx = 0, double yy = 0):x(xx), y(yy) {} 16 | Point operator + (Point& p) { return Point(x + p.x, y + p.y); } 17 | Point operator - (Point& p) { return Point(x - p.x, y - p.y); } 18 | Point operator * (double k) { return Point(x * k, y * k); } 19 | Point operator / (double k) { return Point(x / k, y / k);} 20 | double norm() { return x * x + y * y; } 21 | double abs() { return sqrt(norm()); } 22 | 23 | }; 24 | /* 在类外这样定义! 25 | Point Point::operator * (double k) 26 | { 27 | return Point(x*k, y*k); 28 | } 29 | */ 30 | struct Segment // 线段类 31 | { 32 | Point p1, p2; 33 | Segment(Point pp1, Point pp2):p1(pp1),p2(pp2) {} 34 | }; 35 | 36 | struct Circle // 圆类! 37 | { 38 | Point c; 39 | double r; 40 | Circle(Point p, double radius):c(p),r(radius) {} 41 | }; 42 | 43 | /*类型重定义*/ 44 | typedef Point Vector; // Vector与Point重名,一个点也可以是向量 45 | typedef Segment Line; 46 | typedef vector Polygon; // 一个多边形由多个点构成 47 | 48 | // 计算 49 | 50 | 51 | int main() 52 | { 53 | Vector a(2,1), b(1,2), c, d; 54 | c = a*2; 55 | cout << c.x << " "<< c.y; 56 | return 0; 57 | } -------------------------------------------------------------------------------- /ADT_cpp/LinkList_demo.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-10.13 3 | 链表的创建及其部分基础操作的C++实现 4 | 链表结构如下:(数字代表位置pos) 5 | head(0)-->node(1)-->node(2)-->... 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | 13 | struct node 14 | { 15 | int data; 16 | node* next; 17 | }; 18 | 19 | 20 | node* create(int Array[], int len) // 使用数组生成链表 21 | { 22 | node *head = new node; 23 | head->next = NULL; 24 | node *temp = head; // temp遍历时的控制指针 25 | 26 | for (int i = 0; i < len; i++) 27 | { 28 | node *p = new node; 29 | p->data = Array[i]; 30 | p->next = NULL; 31 | temp->next = p; 32 | temp = temp->next; 33 | } 34 | return head; 35 | } 36 | 37 | int search(node* head, int pos) // 查找第pos位置的元素 38 | { 39 | int cnt = 1; 40 | node* L = head->next; 41 | while(L) 42 | { 43 | if (cnt == pos) 44 | return L->data; 45 | cnt++; 46 | L = L->next; 47 | } 48 | return -1; 49 | } 50 | 51 | node* Insert(node* head, int pos, int x) // 把x插入到第pos位置上 52 | { 53 | int cnt = 0; 54 | node* L = head; 55 | while(L) // 等价于while (L != NULL) 56 | { 57 | if (cnt == pos - 1) // 找到pos-1位置 58 | { 59 | node* new_node = new node; 60 | new_node->data = x; 61 | new_node->next = L->next; 62 | L->next = new_node; 63 | return head; 64 | } 65 | L = L->next; 66 | } 67 | return NULL; 68 | } 69 | 70 | 71 | void Del(node* head, int x) // 删除值==x的节点 72 | { 73 | node* pre = head; 74 | node* temp = pre->next; 75 | 76 | while(temp) 77 | { 78 | if (temp->data == x) 79 | { 80 | pre->next = temp->next; 81 | delete(temp); 82 | temp = pre->next; 83 | } 84 | else 85 | { 86 | pre = pre->next; 87 | temp = temp->next; 88 | } 89 | } 90 | } 91 | 92 | 93 | void Print_List(node* head) 94 | { 95 | node* L = head->next; 96 | while(L) 97 | { 98 | printf("%d ",L->data); 99 | L = L->next; 100 | } 101 | printf("\n"); 102 | } 103 | 104 | 105 | int main() 106 | { 107 | int Array[5] = {5,3,6,1,2}; 108 | // 创建 109 | node* head = create(Array, 5); 110 | Print_List(head); 111 | 112 | // 查找第3个位置的元素值 113 | printf("val = %d\n",search(head, 3)); 114 | 115 | // 插入0到第一个位置上 116 | Insert(head, 1, 0); 117 | Print_List(head); 118 | 119 | // 删除数值是1的结点 120 | Del(head, 1); 121 | Print_List(head); 122 | 123 | return 0; 124 | } 125 | -------------------------------------------------------------------------------- /ADT_py/Deque.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | ''' 3 | 2019-10.10 4 | 双端队列的Python实现 5 | ''' 6 | 7 | class deque(object): 8 | """docstring for deque""" 9 | def __init__(self): 10 | self.items = [] 11 | 12 | def push_back(self, item): 13 | self.items.append(item) 14 | 15 | def push_front(self, item): 16 | self.items.insert(0, item) 17 | 18 | def pop_back(self): 19 | self.items.pop() 20 | 21 | def pop_front(self): 22 | self.items.pop(0) 23 | 24 | def empty(self): 25 | return self.items == [] 26 | 27 | def size(self): 28 | return len(self.items) 29 | 30 | 31 | -------------------------------------------------------------------------------- /ADT_py/Queue.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | ''' 3 | 2019-10.10 4 | 队列的Python实现 5 | ''' 6 | 7 | class queue(): 8 | def __init__(self): 9 | self.items = [] 10 | 11 | def push(self, item): 12 | self.items.append(item) 13 | 14 | def pop(self): 15 | self.items.pop(0) # pop(location) 16 | 17 | def front(self): 18 | return self.items[0] 19 | 20 | def empty(self): # 等于空则返回1 21 | return self.items == [] 22 | 23 | def size(self): 24 | return len(self.items) 25 | 26 | def clear(self): 27 | while not len(self.items) == 0: 28 | self.items.pop() 29 | 30 | 31 | if __name__ == '__main__': 32 | q = queue() 33 | q.push(1) 34 | q.push(2) 35 | q.push(3) 36 | q.clear() 37 | print(q.size()) 38 | 39 | -------------------------------------------------------------------------------- /ADT_py/Stack.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | ''' 3 | 2019-10.10 4 | 栈的实现,测试在main中,直接命令行执行即可 5 | ''' 6 | class stack(): 7 | def __init__(self): 8 | self.items = [] 9 | 10 | def empty(self): # 等于空返回1 11 | return self.items == [] 12 | 13 | def push(self, item): 14 | self.items.append(item) 15 | 16 | def pop(self): 17 | return self.items.pop() # 弹出并返回 18 | 19 | def top(self): 20 | return self.items[len(self.items)-1] 21 | 22 | def size(self): 23 | return len(self.items) 24 | 25 | def clear(self): # 类中的成员函数访问成员变量或成员函数 26 | while not len(self.items) == 0: 27 | self.items.pop() # 使用self.pop()同样可以实现 28 | 29 | if __name__ == '__main__': # 测试 30 | s = stack() 31 | s.push(1) 32 | s.push(2) 33 | s.push(3) 34 | print(s.size()) 35 | s.clear() 36 | print(s.size()) 37 | -------------------------------------------------------------------------------- /ADT_py/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | ''' 3 | 2019-10.10 4 | 抽象数据类型的Python实现 5 | ''' 6 | 7 | from .Stack import * 8 | from .Queue import * 9 | from .Deque import * 10 | -------------------------------------------------------------------------------- /ADT_py/__pycache__/Stack.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberSpaceWang/Algorithm_Interview/f7c083bb6fb348bee5b08f38da648dd72ef81660/ADT_py/__pycache__/Stack.cpython-36.pyc -------------------------------------------------------------------------------- /ADT_py/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberSpaceWang/Algorithm_Interview/f7c083bb6fb348bee5b08f38da648dd72ef81660/ADT_py/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /CH1_Stack_Queue/$: -------------------------------------------------------------------------------- 1 | 10_Max_Min_Num.cpp:*/ 2 | 10_Max_Min_Num.cpp: // freopen("in.txt", "r", stdin); 3 | 10_Max_Min_Num.cpp: // 此时,双端队列维护单的是[i,j]中的最大最小值 4 | 10_Max_Min_Num.cpp: if (qmin.front() == i) // 避免队头元素越界 5 | 11_Mountain_Num.cpp: cin >> n >> p >> m; // 废话 6 | 11_Mountain_Num.cpp: cout< &s) // 获取底层元素值并删除之,其他正常放入! 17 | 3_Inverse_Stack_by_Recursion.cpp: int temp = s.top(); // 当前元素,后续也应当push该值 18 | 3_Inverse_Stack_by_Recursion.cpp: // 回溯部分 19 | 3_Inverse_Stack_by_Recursion.cpp: return result; // 此函数并不完美, 20 | 3_Inverse_Stack_by_Recursion.cpp: reverse(s); // 要获取元素之后再递归, 否则递归无限次! 仔细思考 21 | 3_Inverse_Stack_by_Recursion.cpp: // freopen("in.txt", "r", stdin); 22 | 4_Dog_Cat_Queue.cpp:*/ 23 | 4_Dog_Cat_Queue.cpp: int count, x; // count表示当前动物在总队列数中的排名,num为该动物的编号 24 | 4_Dog_Cat_Queue.cpp:void Pop1(queue &pet) // 删除队列的一个元素 25 | 4_Dog_Cat_Queue.cpp:void Pop_all(queue &pet) // 删除队列中所有元素 26 | 4_Dog_Cat_Queue.cpp: // freopen("in.txt", "r", stdin); 27 | 4_Dog_Cat_Queue.cpp: int x; // 猫狗的编号 28 | 4_Dog_Cat_Queue.cpp: string pet_name; // cat or dog 29 | 4_Dog_Cat_Queue.cpp: while(!Cat.empty() || !Dog.empty()) // 只要有一个队列非空就必须执行 30 | 4_Dog_Cat_Queue.cpp: else if (!Cat.empty()) // Cat非空,Dog空 31 | 4_Dog_Cat_Queue.cpp: else if (s == "pollDog") // 注意何时全部弹出,何时弹出一个元素 32 | 5_Sort_Stack.cpp:*/ 33 | 5_Sort_Stack.cpp: // freopen("in.txt", "r", stdin); 34 | 5_Sort_Stack.cpp: stack s1, s2; // s1是用于存储当前已排序的栈(栈底为min), s2用于存放临时数据 35 | 5_Sort_Stack.cpp: for (int i = 0; i < num; i++) // 边输入边更新排序栈 36 | 5_Sort_Stack.cpp: if (s1.empty() || temp >= s1.top()) // 栈为空或temp比栈顶元素大 37 | 5_Sort_Stack.cpp: else // temp比s1栈顶的元素小 38 | 5_Sort_Stack.cpp: while (!s1.empty() && temp < s1.top()) // temp比s1栈顶元素小时,将s1栈顶丢至s2中. 39 | 5_Sort_Stack.cpp: while (!s2.empty()) // 再把s2中临时存放的元素丢回s1 40 | 6a_Hanoi_Recursive.cpp:*/ 41 | 6a_Hanoi_Recursive.cpp: // 本程序默认中间的柱子固定,若想更灵活使用汉诺塔,可将"mid"改为mid变量 42 | 6a_Hanoi_Recursive.cpp: if (num == 1) // 递归边界 43 | 6a_Hanoi_Recursive.cpp: } // 返回值记录步数 44 | 6a_Hanoi_Recursive.cpp: int part1 = process(num-1, left, mid, right, from, to); // 上层num-1柱子从左->右 45 | 6a_Hanoi_Recursive.cpp: cout << "Move " << num << " from " << from << " to mid\n"; // 底层柱子从from->to,此时from不一定是left 46 | 6a_Hanoi_Recursive.cpp: int part2 = process(num-1, left, mid, right, to, from); // 上层num-1柱子从右->左 47 | 6a_Hanoi_Recursive.cpp: cout << "Move " << num << " from mid to " << to << endl; // 底层柱子从to->from 48 | 6a_Hanoi_Recursive.cpp: int part3 = process(num-1, left, mid, right, from, to); // 上层num-1柱子从左->右 49 | 6a_Hanoi_Recursive.cpp: // freopen("in.txt", "r", stdin); 50 | 6a_Hanoi_Recursive.cpp: int num; // 本题输入太少,可不使用freopen 51 | 7_Max_Windows_Array.cpp:*/ 52 | 7_Max_Windows_Array.cpp:deque dq; // 注意:存元素下标而非元素值! 53 | 7_Max_Windows_Array.cpp: // freopen("in.txt", "r", stdin); 54 | 7_Max_Windows_Array.cpp: int len, w, temp; // len:数组长度,w:窗口大小,temp:当前输入值 55 | 7_Max_Windows_Array.cpp: { // 若队尾元素小于当前元素,弹出队末元素直到队列为空 56 | 7_Max_Windows_Array.cpp: while (!dq.empty() && arr[dq.back()] <= arr[i]) // <= !! 57 | 7_Max_Windows_Array.cpp: dq.push_back(i); // 这一步是对任意i都必须操作的(思考) 58 | 7_Max_Windows_Array.cpp: if (i >= w-1) // 窗口,从w-1下标开始,根据dq输出窗口最大值 59 | 7_Max_Windows_Array.cpp: while (ind <= i - w) // 避免队头元素位于窗口外!用if更好!因为每次只加入一个元素 60 | 8a1_Monotate_Stack.cpp:*/ 61 | 8a1_Monotate_Stack.cpp: // freopen("in.txt", "r", stdin); 62 | 8a1_Monotate_Stack.cpp: for (int j = i-1; j >= 0; j--) // 向左遍历 63 | 8a1_Monotate_Stack.cpp: for (int j = i+1; j < num; j++) // 向右遍历 64 | 8a2_Monotate_Stack.cpp:*/ 65 | 8a2_Monotate_Stack.cpp:stack s; // 存储索引而不是值 66 | 8a2_Monotate_Stack.cpp: // freopen("in.txt", "r", stdin); 67 | 8a2_Monotate_Stack.cpp: while (!s.empty() && vec[s.top()] > vec[i]) // 不是单调栈 68 | 8a2_Monotate_Stack.cpp: lind = s.empty() ? -1 : s.top(); // 判断栈是否为空从而确定左索引 69 | 8a2_Monotate_Stack.cpp: rind = i; // 因为加入i后单调性被破坏,故右索引为i 70 | 8a2_Monotate_Stack.cpp: while (!s.empty()) // 处理最后剩余的元素 71 | 8a2_Monotate_Stack.cpp: arr[val][1] = -1; // 因为单调递增,故右边不存在更小的值,右索引为-1 72 | 8b_Monotate_Stack.cpp:*/ 73 | 8b_Monotate_Stack.cpp: // freopen("in.txt", "r", stdin); 74 | 8b_Monotate_Stack.cpp: for (int i = 0; i < len; i++) // vec[i]在栈外 75 | 8b_Monotate_Stack.cpp: while(!s.empty() && vec[s.top()[0]] > vec[i]) // 若加入vec[i]后不再单调递增,故处理单调的序列 76 | 8b_Monotate_Stack.cpp: s.pop(); // 必须紧跟 77 | 8b_Monotate_Stack.cpp: // 记录repeat中元素的左索引,为栈顶元素最末尾的索引值,注意不是repeat.size(),repeat已被弹出 78 | 8b_Monotate_Stack.cpp: if (!s.empty() && vec[s.top()[0]] == vec[i]) // 添加时需要考虑重复的情况,如果重复 79 | 8b_Monotate_Stack.cpp: vector re_push = s.top(); // 返回值而非引用,故必须pop()出来添加后再push 80 | 8b_Monotate_Stack.cpp: re_push.push_back(i); // i是索引,vec[i]是值,比大小时用vec[i],元素添加时用i 81 | 8b_Monotate_Stack.cpp: else // 不重复直接添加即可 82 | 8b_Monotate_Stack.cpp: while(!s.empty()) // 处理最后的情况 83 | 8b_Monotate_Stack.cpp: arr[repeat[i]][1] = -1; // 因为单调递增,所以右索引为-1 84 | 9_Max_SubMatrix.cpp:*/ 85 | 9_Max_SubMatrix.cpp:int height[maxn]; // 动态切割数组 86 | 9_Max_SubMatrix.cpp:int Get_Max_Area(int height[], int n) // 某一行(n个元素)切割完之后进入该函数计算最大矩形 87 | 9_Max_SubMatrix.cpp: while (!s.empty() && height[s.top()] >= height[i]) // 栈内不允许出现重复的数值情况! 88 | 9_Max_SubMatrix.cpp: int j = s.top(); // 栈顶元素,需要记录左右索引的元素 89 | 9_Max_SubMatrix.cpp: int k = s.empty() ? -1 : s.top(); // 90 | 9_Max_SubMatrix.cpp: int area = (i-1-k)*height[j]; // 事实上应该是(i-1)-(k+1)+1 == i-k-1; 91 | 9_Max_SubMatrix.cpp: s.push(i); // 注意存放的是索引而不是值 92 | 9_Max_SubMatrix.cpp: // freopen("in.txt", "r", stdin); 93 | 9_Max_SubMatrix.cpp: height[j] = matrix[i][j] == 0 ? 0 : height[j] + 1; // +1不能忘了 94 | Binary file a.exe matches 95 | Draft_8c_Monotate_Stack.cpp:*/ 96 | Draft_8c_Monotate_Stack.cpp:stack s, s_temp; // 存储索引而不是值 97 | Draft_8c_Monotate_Stack.cpp:int get_lind(stack &s, int val) // val是栈顶元素索引 98 | Draft_8c_Monotate_Stack.cpp: int result = s.top(); // 取出来存着 99 | Draft_8c_Monotate_Stack.cpp: s.push(result); // 回溯时加回来,不能去掉,否则重复数据的rind无法记录 100 | Draft_8c_Monotate_Stack.cpp: // freopen("in.txt", "r", stdin); 101 | Draft_8c_Monotate_Stack.cpp: while (!s.empty() && vec[s.top()] > vec[i]) // 自顶向下不是单调递增栈 102 | Draft_8c_Monotate_Stack.cpp: s.pop(); // pop后栈顶元素开始与下面相同 103 | Draft_8c_Monotate_Stack.cpp: while (!s.empty()) // 处理最后剩余的元素 104 | Draft_8c_Monotate_Stack.cpp: arr[val][1] = -1; // 因为单调递增,故右边不存在更小的值,右索引为-1 105 | -------------------------------------------------------------------------------- /CH1_Stack_Queue/10_Max_Min_Num.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-10.15 3 | CH1 双端队列--最大值减最小值<=num的子数组数量 4 | 输入: 5 | 5 2 6 | 1 2 3 4 5 7 | 8 | 输出: 9 | 12 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | 18 | deque qmax; 19 | deque qmin; 20 | const int maxn = 1000005; 21 | int arr[maxn]; 22 | 23 | int main() 24 | { 25 | // freopen("in.txt", "r", stdin); 26 | int len, num; 27 | cin >> len >> num; 28 | 29 | for (int i = 0; i < len; i++) 30 | cin >> arr[i]; 31 | int i = 0, j = 0, res = 0; 32 | 33 | while (i < len) 34 | { 35 | while (j < len) 36 | { 37 | while (!qmax.empty() && arr[qmax.back()] <= arr[j]) 38 | qmax.pop_back(); 39 | qmax.push_back(j); 40 | 41 | while (!qmin.empty() && arr[qmin.back()] >= arr[j]) 42 | qmin.pop_back(); 43 | qmin.push_back(j); 44 | // 此时,双端队列维护单的是[i,j]中的最大最小值 45 | if (arr[qmax.front()] - arr[qmin.front()] > num) 46 | break; 47 | j++; 48 | } 49 | res += j - i; 50 | if (qmin.front() == i) // 避免队头元素越界 51 | qmin.pop_front(); 52 | 53 | if (qmax.front() == i) 54 | qmax.pop_front(); 55 | i++; 56 | } 57 | 58 | cout << res << endl; 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /CH1_Stack_Queue/11_Mountain_Num.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | using namespace std; 4 | int main() 5 | { 6 | int t,n,p,m; 7 | cin >> t; 8 | while(t--) 9 | { 10 | cin >> n >> p >> m; // 废话 11 | cout< 13 | #include 14 | #include 15 | #include 16 | using namespace std; 17 | 18 | int main() 19 | { 20 | stack stackData, stackMin; 21 | // freopen("in1.txt", "r", stdin); 22 | int op; 23 | cin >> op; 24 | for (int i = 0; i < op; i++) 25 | { 26 | string s; 27 | cin >> s; 28 | if (s == "push") 29 | { 30 | int num; 31 | cin >> num; 32 | stackData.push(num); // 栈不为空时stackMin.top()会出现段错误 33 | if (stackMin.empty() || num <= stackMin.top()) 34 | stackMin.push(num); 35 | } 36 | else if (s == "pop") 37 | { 38 | int num = stackData.top(); 39 | stackData.pop(); 40 | if (num == stackMin.top()) 41 | stackMin.pop(); 42 | } 43 | else 44 | cout << stackMin.top() << endl; 45 | } 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /CH1_Stack_Queue/1_getMin.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 2019-10.25 3 | CH1 栈--设计一个有getMin功能的栈,测试用例 4 | 6 5 | push 3 6 | push 2 7 | push 1 8 | getMin 9 | pop 10 | getMin 11 | ''' 12 | import pdb 13 | 14 | 15 | n = int(input().strip()) 16 | stack = [] 17 | stack_min = [] 18 | for _ in range(n): 19 | x = input().split() 20 | pdb.set_trace() 21 | 22 | # print(x) 23 | if x[0] == "push": 24 | num = int(x[1]) # 大坑--必须进行int()类型转换,否则存入的是字符串,负数时有bug 25 | stack.append(num) 26 | if stack_min == [] or stack_min[-1] >= num: 27 | stack_min.append(num) 28 | else: 29 | stack_min.append(stack_min[-1]) 30 | elif x[0] == "pop": 31 | stack_min.pop() 32 | stack.pop() 33 | else: 34 | print(stack_min[-1]) 35 | 36 | 37 | -------------------------------------------------------------------------------- /CH1_Stack_Queue/1_getMin_class.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | class Solution 8 | { 9 | public: 10 | stack stackData, stackMin; 11 | void push(int value) 12 | { 13 | stackData.push(value); 14 | if (stackMin.empty() || value <= stackData.top()) 15 | stackMin.push(value); 16 | } 17 | 18 | void pop() 19 | { 20 | int num = stackData.top(); 21 | stackData.pop(); 22 | if (num == stackMin.top()) 23 | stackMin.pop(); 24 | } 25 | 26 | int getMin() 27 | return stackMin.top(); 28 | 29 | }; 30 | 31 | 32 | int main() 33 | { 34 | // freopen("in1.txt", "r", stdin); 35 | int op; 36 | cin >> op; 37 | Solution obj; 38 | for (int i = 0; i < op; i++) 39 | { 40 | string s; 41 | cin >> s; 42 | if (s == "push") 43 | { 44 | int num; 45 | cin >> num; 46 | obj.push(num); 47 | } 48 | else if (s == "pop") 49 | obj.pop(); 50 | else 51 | cout << obj.getMin() << endl; 52 | } 53 | return 0; 54 | } -------------------------------------------------------------------------------- /CH1_Stack_Queue/2_stack_queue.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-9.24 3 | CH1 栈--使用两个栈模拟队列,测试数据: 4 | 6 5 | add 1 6 | add 2 7 | add 3 8 | peek 9 | poll 10 | peek 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | using namespace std; 18 | 19 | stack spush, spop; 20 | 21 | void ToPop() // 将push栈的元素全部压入pop栈中 22 | { 23 | if (spop.empty()) // pop栈为空,需要从push栈中一次性导入(这个判断条件是必须的) 24 | { 25 | while (!spush.empty()) 26 | { 27 | int num = spush.top(); 28 | spush.pop(); 29 | spop.push(num); 30 | } 31 | } 32 | } 33 | 34 | 35 | int main() 36 | { 37 | // freopen("in.txt", "r", stdin); 38 | int op; 39 | cin >> op; 40 | for (int i = 0; i < op; i++) 41 | { 42 | string s; 43 | cin >> s; 44 | if (s == "add") 45 | { 46 | int num; 47 | cin >> num; 48 | spush.push(num); 49 | } 50 | else if (s == "poll") 51 | { 52 | ToPop(); 53 | spop.pop(); 54 | } 55 | else 56 | { 57 | ToPop(); 58 | cout << spop.top() << endl; 59 | } 60 | } 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /CH1_Stack_Queue/3_Inverse_Stack_by_Recursion.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-9.26 3 | CH1 栈--使用递归函数和栈操作逆序一个栈 4 | 测试样例 5 | 5 6 | 1 2 3 4 5 7 | */ 8 | #include 9 | #include 10 | #include 11 | using namespace std; 12 | 13 | stack s; 14 | 15 | int Get_Remove_Last_Ele(stack &s) // 获取底层元素值并删除之,其他正常放入! 16 | { 17 | int temp = s.top(); // 当前元素,后续也应当push该值 18 | s.pop(); 19 | if (s.empty()) 20 | return temp; 21 | else 22 | { 23 | int result = Get_Remove_Last_Ele(s); 24 | // 回溯部分 25 | s.push(temp); 26 | return result; // 此函数并不完美, 27 | } 28 | } 29 | 30 | void reverse(stack &s) 31 | { 32 | if (s.empty()) 33 | return ; 34 | int last = Get_Remove_Last_Ele(s); 35 | reverse(s); // 要获取元素之后再递归, 否则递归无限次! 仔细思考 36 | cout << last << " "; 37 | } 38 | 39 | 40 | int main() 41 | { 42 | // freopen("in.txt", "r", stdin); 43 | int num; 44 | cin >> num; 45 | for (int i = 0; i < num; i++) 46 | { 47 | int val; 48 | cin >> val; 49 | s.push(val); 50 | } 51 | reverse(s); 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /CH1_Stack_Queue/3_Inverse_Stack_by_Recursion.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 2019-9.26 3 | CH1 栈--使用递归函数和栈操作逆序一个栈 4 | 测试样例 5 | 5 6 | 1 2 3 4 5 7 | ''' 8 | import pdb 9 | 10 | pdb.set_trace() 11 | x = input().strip() 12 | print(x) 13 | nums = [int(i) for i in input().split()] 14 | print(nums) 15 | 16 | -------------------------------------------------------------------------------- /CH1_Stack_Queue/4_Dog_Cat_Queue.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-10.3 3 | CH1 队列--猫狗队列 4 | 测试用例: 5 | 11 6 | add cat 1 7 | add dog 2 8 | pollAll 9 | isEmpty 10 | add cat 5 11 | isDogEmpty 12 | pollCat 13 | add dog 10 14 | add cat 199 15 | pollDog 16 | pollAll 17 | 18 | 结果: 19 | cat 1 20 | dog 2 21 | yes 22 | yes 23 | cat 5 24 | dog 10 25 | cat 199 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | using namespace std; 33 | 34 | struct Pet 35 | { 36 | string pet_name; 37 | int count, x; // count表示当前动物在总队列数中的排名,num为该动物的编号 38 | Pet(int cnt, int xx, string pet):count(cnt), x(xx), pet_name(pet) {} 39 | }; 40 | 41 | 42 | void Pop1(queue &pet) // 删除队列的一个元素 43 | { 44 | Pet animal = pet.front(); 45 | pet.pop(); 46 | cout << animal.pet_name << " " << animal.x << endl; 47 | } 48 | 49 | void Pop_all(queue &pet) // 删除队列中所有元素 50 | { 51 | while (!pet.empty()) 52 | { 53 | Pet animal = pet.front(); 54 | pet.pop(); 55 | cout << animal.pet_name << " " << animal.x << endl; 56 | } 57 | } 58 | 59 | void is_empty_queue(queue pet) 60 | { 61 | if (pet.empty()) 62 | cout << "yes" << endl; 63 | else 64 | cout << "no" << endl; 65 | } 66 | 67 | int main() 68 | { 69 | // freopen("in.txt", "r", stdin); 70 | int step, total = 0; 71 | cin >> step; 72 | queue Dog, Cat; 73 | for (int i = 0; i < step; i++) 74 | { 75 | string s; 76 | cin >> s; 77 | if (s == "add") 78 | { 79 | int x; // 猫狗的编号 80 | string pet_name; // cat or dog 81 | cin >> pet_name >> x; 82 | if (pet_name == "dog") 83 | Dog.push(Pet(total++, x, "dog")); 84 | else 85 | Cat.push(Pet(total++, x, "cat")); 86 | } 87 | else if (s == "pollAll") 88 | { 89 | while(!Cat.empty() || !Dog.empty()) // 只要有一个队列非空就必须执行 90 | { 91 | if (!Cat.empty() && !Dog.empty()) 92 | { 93 | Pet cat = Cat.front(); 94 | Pet dog = Dog.front(); 95 | if (cat.count < dog.count) 96 | Pop1(Cat); 97 | else 98 | Pop1(Dog); 99 | } 100 | else if (!Cat.empty()) // Cat非空,Dog空 101 | Pop1(Cat); 102 | else 103 | Pop1(Dog); 104 | } 105 | } 106 | else if (s == "pollDog") // 注意何时全部弹出,何时弹出一个元素 107 | Pop_all(Dog); 108 | else if (s == "pollCat") 109 | Pop_all(Cat); 110 | else if (s == "isEmpty") 111 | { 112 | if (Dog.empty() && Cat.empty()) 113 | cout << "yes" << endl; 114 | else 115 | cout << "no" << endl; 116 | } 117 | else if (s == "isDogEmpty") 118 | is_empty_queue(Dog); 119 | else 120 | is_empty_queue(Cat); 121 | } 122 | return 0; 123 | } 124 | -------------------------------------------------------------------------------- /CH1_Stack_Queue/5_Sort_Stack.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-9.28 3 | CH1 栈--用一个栈实现另一个栈的排序 4 | 测试样例: 5 | 5 6 | 5 8 4 3 6 7 | 8 | 输出: 9 | 8 6 5 4 3 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | using namespace std; 16 | 17 | int main() 18 | { 19 | // freopen("in.txt", "r", stdin); 20 | stack s1, s2; // s1是用于存储当前已排序的栈(栈底为min), s2用于存放临时数据 21 | int num; 22 | cin >> num; 23 | for (int i = 0; i < num; i++) // 边输入边更新排序栈 24 | { 25 | int temp; 26 | cin >> temp; 27 | if (s1.empty() || temp >= s1.top()) // 栈为空或temp比栈顶元素大 28 | s1.push(temp); 29 | else // temp比s1栈顶的元素小 30 | { 31 | while (!s1.empty() && temp < s1.top()) // temp比s1栈顶元素小时,将s1栈顶丢至s2中. 32 | s2.push(s1.top()); 33 | s1.pop(); 34 | } 35 | s1.push(temp); 36 | while (!s2.empty()) // 再把s2中临时存放的元素丢回s1 37 | { 38 | s1.push(s2.top()); 39 | s2.pop(); 40 | } 41 | } 42 | } 43 | while (!s1.empty()) 44 | { 45 | cout << s1.top() << " "; 46 | s1.pop(); 47 | } 48 | } -------------------------------------------------------------------------------- /CH1_Stack_Queue/6a_Hanoi_Recursive.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-10.8 3 | CH1 栈--使用栈模拟汉诺塔 4 | 输入样例: 5 | 2 6 | 7 | 输出: 8 | Move 1 from left to mid 9 | Move 1 from mid to right 10 | Move 2 from left to mid 11 | Move 1 from right to mid 12 | Move 1 from mid to left 13 | Move 2 from mid to right 14 | Move 1 from left to mid 15 | Move 1 from mid to right 16 | It will move 8 steps. 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | using namespace std; 23 | // 本程序默认中间的柱子固定,若想更灵活使用汉诺塔,可将"mid"改为mid变量 24 | int process(int num, string left, string mid, string right, string from, string to) 25 | { 26 | if (num == 1) // 递归边界 27 | { 28 | cout << "Move 1 from " << from << " to mid\n"; 29 | cout << "Move 1 from " << "mid to " << to << endl; 30 | return 2; 31 | } // 返回值记录步数 32 | int part1 = process(num-1, left, mid, right, from, to); // 上层num-1柱子从左->右 33 | cout << "Move " << num << " from " << from << " to mid\n"; // 底层柱子从from->to,此时from不一定是left 34 | int part2 = process(num-1, left, mid, right, to, from); // 上层num-1柱子从右->左 35 | cout << "Move " << num << " from mid to " << to << endl; // 底层柱子从to->from 36 | int part3 = process(num-1, left, mid, right, from, to); // 上层num-1柱子从左->右 37 | return part1 + part2 + part3 + 2; 38 | } 39 | 40 | int main() 41 | { 42 | // freopen("in.txt", "r", stdin); 43 | int num; // 本题输入太少,可不使用freopen 44 | cin >> num; 45 | string left = "left", mid = "mid", right="right"; 46 | int steps = process(num, left, mid, right, left, right); 47 | cout << "It will move "<< steps << " steps." << endl; 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /CH1_Stack_Queue/7_Max_Windows_Array.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-10.6 3 | CH1 双端队列--生成窗口最大值数组 4 | 测试样例: 5 | 8 3 6 | 4 3 5 4 3 3 6 7 7 | 8 | 输出: 9 | 5 5 5 4 6 7 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | using namespace std; 17 | 18 | deque dq; // 注意:存元素下标而非元素值! 19 | vector arr; 20 | 21 | int main() 22 | { 23 | // freopen("in.txt", "r", stdin); 24 | int len, w, temp; // len:数组长度,w:窗口大小,temp:当前输入值 25 | cin >> len >> w; 26 | for (int i = 0; i < len; i++) 27 | { 28 | cin >> temp; 29 | arr.push_back(temp); 30 | } 31 | 32 | for (int i = 0; i < len; i++) 33 | { // 若队尾元素小于当前元素,弹出队末元素直到队列为空 34 | while (!dq.empty() && arr[dq.back()] <= arr[i]) // <= !! 35 | dq.pop_back(); 36 | dq.push_back(i); // 这一步是对任意i都必须操作的(思考) 37 | 38 | if (i >= w-1) // 窗口,从w-1下标开始,根据dq输出窗口最大值 39 | { 40 | int ind = dq.front(); 41 | while (ind <= i - w) // 避免队头元素位于窗口外!用if更好!因为每次只加入一个元素 42 | { 43 | dq.pop_front(); 44 | ind = dq.front(); 45 | } 46 | cout << arr[ind] << " "; 47 | } 48 | } 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /CH1_Stack_Queue/8a1_Monotate_Stack.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-10.11 3 | 栈--单调栈结构--基础 4 | 时间O(N^2) 5 | 测试样例: 6 | 7 7 | 3 4 1 5 6 2 7 8 | 9 | 输出: 10 | -1 2 11 | 0 2 12 | -1 -1 13 | 2 5 14 | 3 5 15 | 2 -1 16 | 5 -1 17 | */ 18 | #include 19 | #include 20 | #include 21 | using namespace std; 22 | 23 | vector vec; 24 | 25 | int main() 26 | { 27 | // freopen("in.txt", "r", stdin); 28 | int num, val; 29 | cin >> num; 30 | for (int i = 0; i < num; i++) 31 | { 32 | cin >> val; 33 | vec.push_back(val); 34 | } 35 | 36 | for (int i = 0; i < num; i++) 37 | { 38 | int lind = -1, rind = -1; 39 | for (int j = i-1; j >= 0; j--) // 向左遍历 40 | { 41 | if (vec[j] < vec[i]) 42 | { 43 | lind = j; 44 | break; 45 | } 46 | } 47 | cout << lind << " "; 48 | 49 | for (int j = i+1; j < num; j++) // 向右遍历 50 | { 51 | if (vec[j] < vec[i]) 52 | { 53 | rind = j; 54 | break; 55 | } 56 | } 57 | cout << rind << endl; 58 | } 59 | return 0; 60 | } -------------------------------------------------------------------------------- /CH1_Stack_Queue/8a2_Monotate_Stack.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-10.11 3 | CH1 栈--单调栈结构--基础 4 | 时间O(N),空间O(N) 5 | 测试样例: 6 | 7 7 | 3 4 1 5 6 2 7 8 | 9 | 输出: 10 | -1 2 11 | 0 2 12 | -1 -1 13 | 2 5 14 | 3 5 15 | 2 -1 16 | 5 -1 17 | */ 18 | #include 19 | #include 20 | #include 21 | #include 22 | using namespace std; 23 | 24 | const int maxn = 1000005; 25 | int arr[maxn][2]; 26 | vector vec; 27 | stack s; // 存储索引而不是值 28 | 29 | int main() 30 | { 31 | // freopen("in.txt", "r", stdin); 32 | int len, val, lind, rind; 33 | cin >> len; 34 | for (int i = 0; i < len; i++) 35 | { 36 | cin >> val; 37 | vec.push_back(val); 38 | } 39 | 40 | for (int i = 0; i < len; i++) 41 | { 42 | while (!s.empty() && vec[s.top()] > vec[i]) // 不是单调栈 43 | { 44 | int val = s.top(); 45 | s.pop(); 46 | lind = s.empty() ? -1 : s.top(); // 判断栈是否为空从而确定左索引 47 | rind = i; // 因为加入i后单调性被破坏,故右索引为i 48 | arr[val][0] = lind; 49 | arr[val][1] = rind; 50 | } 51 | s.push(i); 52 | } 53 | 54 | while (!s.empty()) // 处理最后剩余的元素 55 | { 56 | int val = s.top(); 57 | s.pop(); 58 | lind = s.empty() ? -1 : s.top(); 59 | arr[val][0] = lind; 60 | arr[val][1] = -1; // 因为单调递增,故右边不存在更小的值,右索引为-1 61 | } 62 | 63 | for (int i = 0; i < len; i++) 64 | cout << arr[i][0] << " " << arr[i][1] << endl; 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /CH1_Stack_Queue/8b_Monotate_Stack.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-10.11 3 | CH1 栈--单调栈结构--进阶,有重复元素 4 | 测试样例: 5 | 9 6 | 3 1 3 4 3 5 3 2 2 7 | 8 | 输出: 9 | -1 1 10 | -1 -1 11 | 1 7 12 | 2 4 13 | 1 7 14 | 4 6 15 | 1 7 16 | 1 -1 17 | 1 -1 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | using namespace std; 25 | 26 | const int maxn = 1000005; 27 | stack > s; 28 | int arr[maxn][2]; 29 | vector vec; 30 | 31 | int main() 32 | { 33 | // freopen("in.txt", "r", stdin); 34 | int len, val, lind, rind; 35 | cin >> len; 36 | for (int i = 0; i < len; i++) 37 | { 38 | cin >> val; 39 | vec.push_back(val); 40 | } 41 | 42 | for (int i = 0; i < len; i++) // vec[i]在栈外 43 | { 44 | while(!s.empty() && vec[s.top()[0]] > vec[i]) // 若加入vec[i]后不再单调递增,故处理单调的序列 45 | { 46 | vector repeat = s.top(); 47 | s.pop(); // 必须紧跟 48 | // 记录repeat中元素的左索引,为栈顶元素最末尾的索引值,注意不是repeat.size(),repeat已被弹出 49 | int lind = s.empty() ? -1 : s.top()[s.top().size()-1]; 50 | for (int j = 0; j < repeat.size(); j++) 51 | { 52 | arr[repeat[j]][0] = lind; 53 | arr[repeat[j]][1] = i; 54 | } 55 | } 56 | if (!s.empty() && vec[s.top()[0]] == vec[i]) // 添加时需要考虑重复的情况,如果重复 57 | { 58 | vector re_push = s.top(); // 返回值而非引用,故必须pop()出来添加后再push 59 | s.pop(); 60 | re_push.push_back(i); // i是索引,vec[i]是值,比大小时用vec[i],元素添加时用i 61 | s.push(re_push); 62 | } 63 | else // 不重复直接添加即可 64 | { 65 | vector re_push; 66 | re_push.push_back(i); 67 | s.push(re_push); 68 | } 69 | } 70 | 71 | while(!s.empty()) // 处理最后的情况 72 | { 73 | vector repeat = s.top(); 74 | s.pop(); 75 | int lind = s.empty() ? -1 : s.top()[s.top().size()-1]; 76 | for (int i = 0; i < repeat.size(); i++) 77 | { 78 | arr[repeat[i]][0] = lind; 79 | arr[repeat[i]][1] = -1; // 因为单调递增,所以右索引为-1 80 | } 81 | } 82 | 83 | for (int i = 0; i < len; i++) 84 | cout << arr[i][0] << " " << arr[i][1] << endl; 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /CH1_Stack_Queue/9_Max_SubMatrix.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-10.15 3 | CH1 栈--最大子矩阵 4 | 输入样例: 5 | 3 4 6 | 1 0 1 1 7 | 1 1 1 1 8 | 1 1 1 0 9 | 10 | 输出: 11 | 6 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | using namespace std; 21 | 22 | const int maxn = 2005; 23 | int matrix[maxn][maxn]; 24 | int height[maxn]; // 动态切割数组 25 | stack s; 26 | 27 | 28 | int Get_Max_Area(int height[], int n) // 某一行(n个元素)切割完之后进入该函数计算最大矩形 29 | { 30 | int max_area = -1; 31 | for (int i = 0; i < n; i++) 32 | { 33 | while (!s.empty() && height[s.top()] >= height[i]) // 栈内不允许出现重复的数值情况! 34 | { 35 | int j = s.top(); // 栈顶元素,需要记录左右索引的元素 36 | s.pop(); 37 | int k = s.empty() ? -1 : s.top(); // 38 | int area = (i-1-k)*height[j]; // 事实上应该是(i-1)-(k+1)+1 == i-k-1; 39 | max_area = max(area, max_area); 40 | } 41 | s.push(i); // 注意存放的是索引而不是值 42 | } 43 | 44 | while (!s.empty()) 45 | { 46 | int j = s.top(); 47 | s.pop(); 48 | int k = s.empty() ? -1 : s.top(); 49 | int area = (n-1-k)*height[j]; 50 | max_area = max(area, max_area); 51 | } 52 | return max_area; 53 | 54 | } 55 | 56 | int main() 57 | { 58 | // freopen("in.txt", "r", stdin); 59 | int m, n; 60 | cin >> m >> n; 61 | for (int i = 0; i < m; i++) 62 | for (int j = 0; j < n; j++) 63 | cin >> matrix[i][j]; 64 | memset(height, 0, sizeof(height)); 65 | 66 | int max_area = -1; 67 | for (int i = 0; i < m; i++) 68 | { 69 | for (int j = 0; j < n; j++) 70 | { 71 | height[j] = matrix[i][j] == 0 ? 0 : height[j] + 1; // +1不能忘了 72 | } 73 | int temp_max = Get_Max_Area(height, n); 74 | max_area = max(max_area, temp_max); 75 | } 76 | 77 | cout << max_area << endl; 78 | 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /CH1_Stack_Queue/Draft_8c_Monotate_Stack.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-10.11 3 | 本代码提交超时:通过75%用例 4 | CH1 栈--单调栈结构--进阶,有重复 5 | 测试样例: 6 | 9 7 | 3 1 3 4 3 5 3 2 2 8 | 9 | 输出: 10 | -1 1 11 | -1 -1 12 | 1 7 13 | 2 4 14 | 1 7 15 | 4 6 16 | 1 7 17 | 1 -1 18 | 1 -1 19 | */ 20 | #include 21 | #include 22 | #include 23 | #include 24 | using namespace std; 25 | 26 | const int maxn = 1000005; 27 | int arr[maxn][2]; 28 | vector vec; 29 | stack s, s_temp; // 存储索引而不是值 30 | int k = -1; 31 | 32 | int get_lind(stack &s, int val) // val是栈顶元素索引 33 | { 34 | if (s.empty()) 35 | { 36 | k = -1; 37 | return k; 38 | } 39 | if (vec[s.top()] != vec[val]) 40 | { 41 | k = s.top(); 42 | return k; 43 | } 44 | int result = s.top(); // 取出来存着 45 | s.pop(); 46 | arr[result][0] = get_lind(s, val); 47 | s.push(result); // 回溯时加回来,不能去掉,否则重复数据的rind无法记录 48 | return k; 49 | } 50 | 51 | int main() 52 | { 53 | // freopen("in.txt", "r", stdin); 54 | int len, val, lind, rind; 55 | cin >> len; 56 | for (int i = 0; i < len; i++) 57 | { 58 | cin >> val; 59 | vec.push_back(val); 60 | } 61 | 62 | for (int i = 0; i < len; i++) 63 | { 64 | while (!s.empty() && vec[s.top()] > vec[i]) // 自顶向下不是单调递增栈 65 | { 66 | int val = s.top(); 67 | s.pop(); // pop后栈顶元素开始与下面相同 68 | arr[val][0] = get_lind(s, val); 69 | arr[val][1] = i; 70 | while (!s.empty() && vec[val] == vec[s.top()]) 71 | { 72 | val = s.top(); 73 | arr[val][1] = i; 74 | s.pop(); 75 | } 76 | } 77 | s.push(i); 78 | } 79 | 80 | while (!s.empty()) // 处理最后剩余的元素 81 | { 82 | int val = s.top(); 83 | s.pop(); 84 | arr[val][0] = get_lind(s, val); 85 | arr[val][1] = -1; // 因为单调递增,故右边不存在更小的值,右索引为-1 86 | while (!s.empty() && vec[val] == vec[s.top()]) 87 | { 88 | val = s.top(); 89 | arr[val][1] = -1; 90 | s.pop(); 91 | } 92 | } 93 | 94 | for (int i = 0; i < len; i++) 95 | cout << arr[i][0] << " " << arr[i][1] << endl; 96 | return 0; 97 | } 98 | -------------------------------------------------------------------------------- /CH1_Stack_Queue/ans.txt: -------------------------------------------------------------------------------- 1 | 6 2 | 1 3 | 2 4 | 3 5 | 4 6 | 5 7 | 6 8 | -------------------------------------------------------------------------------- /CH1_Stack_Queue/in.txt: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 3 -------------------------------------------------------------------------------- /CH1_Stack_Queue/out.txt: -------------------------------------------------------------------------------- 1 | 5 2 | 1 3 | 2 4 | 3 5 | 4 6 | 5 7 | -------------------------------------------------------------------------------- /CH2_LinkedList/10a_Add_2LinkedList.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-10.30 3 | 链表--将两个单链表相加链表 4 | 时间O(N),空间O(N) 5 | 输入: 6 | 3 2 7 | 9 3 7 8 | 6 3 9 | 输出: 10 | 1 0 0 0 11 | */ 12 | 13 | # include 14 | using namespace std; 15 | 16 | struct list_node{ 17 | int val; 18 | struct list_node * next; 19 | }; 20 | 21 | list_node * input_list(int n) 22 | { 23 | int val; 24 | list_node * phead = new list_node(); 25 | list_node * cur_pnode = phead; 26 | for (int i = 1; i <= n; ++i) { 27 | scanf("%d", &val); 28 | if (i == 1) { 29 | cur_pnode->val = val; 30 | cur_pnode->next = NULL; 31 | } 32 | else { 33 | list_node * new_pnode = new list_node(); 34 | new_pnode->val = val; 35 | new_pnode->next = NULL; 36 | cur_pnode->next = new_pnode; 37 | cur_pnode = new_pnode; 38 | } 39 | } 40 | return phead; 41 | } 42 | 43 | 44 | /*--------------------------------------Code Here--------------------------------------*/ 45 | 46 | list_node * add_list(list_node * head1, list_node * head2) // 要求返回链表 47 | { 48 | //////在下面完成代码 49 | stack s1, s2; 50 | while (head1) 51 | { 52 | s1.push(head1->val); 53 | head1 = head1->next; 54 | } 55 | while (head2) 56 | { 57 | s2.push(head2->val); 58 | head2 = head2->next; 59 | } 60 | int add=0, val1, val2, tot; 61 | list_node* cur = NULL; 62 | while (!s1.empty() || !s2.empty()) 63 | { 64 | val1 = s1.empty() ? 0 : s1.top(); 65 | if (!s1.empty()) 66 | s1.pop(); 67 | val2 = s2.empty() ? 0 : s2.top(); 68 | if (!s2.empty()) 69 | s2.pop(); 70 | tot = val1 + val2 + add; 71 | if (tot >= 10) 72 | { 73 | tot -= 10; 74 | add = 1; 75 | } 76 | else 77 | add = 0; 78 | list_node* node = new list_node(); 79 | node->val = tot; 80 | node->next = cur; 81 | cur = node; 82 | } 83 | if (add) 84 | { 85 | list_node* node = new list_node(); 86 | node->val = add; 87 | node->next = cur; 88 | cur = node; 89 | } 90 | return cur; 91 | } 92 | 93 | 94 | void print_list(list_node * head) 95 | { 96 | while (head != NULL) { 97 | printf("%d ", head->val); 98 | head = head->next; 99 | } 100 | puts(""); 101 | } 102 | 103 | int main () 104 | { 105 | int n, m; 106 | scanf("%d%d", &n, &m); 107 | list_node * head1 = input_list(n), * head2 = input_list(m); 108 | list_node * new_head = add_list(head1, head2); 109 | print_list(new_head); 110 | return 0; 111 | } -------------------------------------------------------------------------------- /CH2_LinkedList/10b_Add_2LinkedList.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-10.30 3 | 链表--将两个单链表相加链表 4 | 时间O(N),空间O(1) 5 | 输入: 6 | 3 2 7 | 9 3 7 8 | 6 3 9 | 输出: 10 | 1 0 0 0 11 | */ 12 | 13 | # include 14 | using namespace std; 15 | 16 | struct list_node{ 17 | int val; 18 | struct list_node * next; 19 | }; 20 | 21 | list_node * input_list(int n) 22 | { 23 | int val; 24 | list_node * phead = new list_node(); 25 | list_node * cur_pnode = phead; 26 | for (int i = 1; i <= n; ++i) { 27 | scanf("%d", &val); 28 | if (i == 1) { 29 | cur_pnode->val = val; 30 | cur_pnode->next = NULL; 31 | } 32 | else { 33 | list_node * new_pnode = new list_node(); 34 | new_pnode->val = val; 35 | new_pnode->next = NULL; 36 | cur_pnode->next = new_pnode; 37 | cur_pnode = new_pnode; 38 | } 39 | } 40 | return phead; 41 | } 42 | 43 | 44 | /*--------------------------------------Code Here--------------------------------------*/ 45 | 46 | list_node* reverse(list_node* head) // 反转链表 47 | { 48 | list_node* pre = NULL, *cur = head, *next = NULL; 49 | while (cur) 50 | { 51 | next = cur->next; 52 | cur->next = pre; 53 | pre = cur; 54 | cur = next; 55 | } 56 | return pre; 57 | } 58 | 59 | list_node * add_list(list_node * head1, list_node * head2) // 要求返回链表 60 | { 61 | //////在下面完成代码 62 | head1 = reverse(head1); 63 | head2 = reverse(head2); 64 | int tot, val1, val2, add=0; 65 | list_node* cur = NULL; 66 | while (head1 || head2) 67 | { 68 | val1 = head1==NULL? 0 : head1->val; 69 | head1 = head1==NULL ? NULL : head1->next; 70 | val2 = head2==NULL? 0 : head2->val; 71 | head2 = head2==NULL ? NULL : head2->next; 72 | tot = val1 + val2 + add; 73 | if (tot >= 10) // 73-79行可以简化为:add=tot/10, tot=tot%10; 74 | { 75 | add = 1; 76 | tot -= 10; 77 | } 78 | else 79 | add = 0; 80 | list_node* node = new list_node(); 81 | node->val = tot; 82 | node->next = cur; 83 | cur = node; 84 | } 85 | if (add) 86 | { 87 | list_node* node = new list_node(); 88 | node->val = add; 89 | node->next = cur; 90 | cur = node; 91 | } 92 | return cur; 93 | } 94 | 95 | 96 | void print_list(list_node * head) 97 | { 98 | while (head != NULL) { 99 | printf("%d ", head->val); 100 | head = head->next; 101 | } 102 | puts(""); 103 | } 104 | 105 | int main () 106 | { 107 | int n, m; 108 | scanf("%d%d", &n, &m); 109 | list_node * head1 = input_list(n), * head2 = input_list(m); 110 | list_node * new_head = add_list(head1, head2); 111 | print_list(new_head); 112 | return 0; 113 | } -------------------------------------------------------------------------------- /CH2_LinkedList/12a_Reverse_KNode.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-11.7 3 | 链表--将链表的每K个节点逆序 4 | 时间O(N),空间O(N/2) 5 | 输入: 6 | 5 7 | 1 2 3 4 5 8 | 3 9 | 输出: 10 | 3 2 1 4 5 11 | */ 12 | 13 | # include 14 | using namespace std; 15 | 16 | struct list_node{ 17 | int val; 18 | struct list_node * next; 19 | }; 20 | 21 | list_node * input_list(int n) 22 | { 23 | int val; 24 | list_node * phead = new list_node(); 25 | list_node * cur_pnode = phead; 26 | for (int i = 1; i <= n; ++i) { 27 | scanf("%d", &val); 28 | if (i == 1) { 29 | cur_pnode->val = val; 30 | cur_pnode->next = NULL; 31 | } 32 | else { 33 | list_node * new_pnode = new list_node(); 34 | new_pnode->val = val; 35 | new_pnode->next = NULL; 36 | cur_pnode->next = new_pnode; 37 | cur_pnode = new_pnode; 38 | } 39 | } 40 | return phead; 41 | } 42 | 43 | 44 | /*--------------------------------------Code Here--------------------------------------*/ 45 | 46 | stack s; 47 | 48 | list_node* Reverse_List(list_node* head, int K) // 反转链表 49 | { 50 | int temp = 0; 51 | list_node* cur = head, *next = NULL, *pre = NULL; 52 | list_node* new_head = head, *fir = NULL; 53 | while (cur) 54 | { 55 | next = cur->next; 56 | temp++; 57 | s.push(cur); // cur链表中顺序遍历的值 58 | if (temp % K == 0) 59 | { 60 | fir = s.top(); // 栈顶元素 61 | if (pre) 62 | pre->next = fir; 63 | s.pop(); 64 | while (!s.empty()) 65 | { 66 | fir->next = s.top(); 67 | fir = s.top(); 68 | s.pop(); 69 | } 70 | pre = fir; // 倒序后的最后一个!3-2-1中的1 71 | pre->next = next; // 针对32145和321654的前者(默认情况,若有改动后续进行调整) 72 | new_head = new_head==head ? cur : new_head; 73 | } 74 | cur = next; 75 | } 76 | return new_head; 77 | } 78 | 79 | 80 | void print_list(list_node * head) 81 | { 82 | while (head != NULL) { 83 | printf("%d ", head->val); 84 | head = head->next; 85 | } 86 | puts(""); 87 | } 88 | 89 | int main () 90 | { 91 | int n, K; 92 | scanf("%d", &n); 93 | list_node * head = input_list(n); 94 | scanf("%d", &K); 95 | list_node * new_head = Reverse_List(head, K); 96 | print_list(new_head); 97 | return 0; 98 | } -------------------------------------------------------------------------------- /CH2_LinkedList/12b_Reverse_KNode.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-11.16 3 | 链表--将链表的每K个节点逆序 4 | 时间O(N),空间O(1) 5 | 输入: 6 | 5 7 | 1 2 3 4 5 8 | 3 9 | 输出: 10 | 3 2 1 4 5 11 | */ 12 | 13 | # include 14 | using namespace std; 15 | 16 | struct list_node{ 17 | int val; 18 | struct list_node * next; 19 | }; 20 | 21 | list_node * input_list(int n) 22 | { 23 | int val; 24 | list_node * phead = new list_node(); 25 | list_node * cur_pnode = phead; 26 | for (int i = 1; i <= n; ++i) { 27 | scanf("%d", &val); 28 | if (i == 1) { 29 | cur_pnode->val = val; 30 | cur_pnode->next = NULL; 31 | } 32 | else { 33 | list_node * new_pnode = new list_node(); 34 | new_pnode->val = val; 35 | new_pnode->next = NULL; 36 | cur_pnode->next = new_pnode; 37 | cur_pnode = new_pnode; 38 | } 39 | } 40 | return phead; 41 | } 42 | 43 | 44 | /*--------------------------------------Code Here--------------------------------------*/ 45 | 46 | void Reverse_subList(list_node* head, list_node* tail) // 如果要逆序123 4,则head为1,tral为4 47 | { 48 | list_node* cur = head, *next = NULL, *pre = NULL; 49 | while (cur != tail) 50 | { 51 | next = cur->next; 52 | cur->next = pre; 53 | pre = cur; 54 | cur = next; 55 | } 56 | // return tail; 57 | } 58 | 59 | 60 | list_node* Reverse_List(list_node* head, int K) // 反转链表 61 | { 62 | int temp = 0; 63 | list_node* cur = head, *next = NULL, *pre = NULL; 64 | list_node* new_head = head, *fir = NULL; 65 | list_node* h = head; 66 | while (cur) 67 | { 68 | temp++; 69 | next = cur->next; 70 | if (temp % K == 0) 71 | { 72 | if (pre) // 用于解决第一次不需要匹配的情况 73 | pre->next = cur; 74 | Reverse_subList(h, next); 75 | pre = h; // pre记录上次需要逆序片段的后缀123的1 76 | pre->next = next; 77 | h = next; 78 | new_head = new_head==head ? cur : new_head; 79 | } 80 | cur = next; // 这里一定不能写成cur=cur->next 81 | } 82 | return new_head; 83 | } 84 | 85 | 86 | void print_list(list_node * head) 87 | { 88 | while (head != NULL) { 89 | printf("%d ", head->val); 90 | head = head->next; 91 | } 92 | puts(""); 93 | } 94 | 95 | int main () 96 | { 97 | int n, K; 98 | scanf("%d", &n); 99 | list_node * head = input_list(n); 100 | scanf("%d", &K); 101 | list_node * new_head = Reverse_List(head, K); 102 | print_list(new_head); 103 | return 0; 104 | } -------------------------------------------------------------------------------- /CH2_LinkedList/13a_Delete_Repeat_node.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 删除无序单链表中重复出现的节点 3 | 时间:O(N),空间:O(N) 4 | 输入: 5 | 5 6 | 1 3 2 3 1 7 | 输出: 8 | 1 2 3 9 | */ 10 | 11 | 12 | # include 13 | using namespace std; 14 | 15 | struct list_node{ 16 | int val; 17 | struct list_node * next; 18 | }; 19 | 20 | list_node * input_list() 21 | { 22 | int val, n; 23 | scanf("%d", &n); 24 | list_node * phead = new list_node(); 25 | list_node * cur_pnode = phead; 26 | for (int i = 1; i <= n; ++i) { 27 | scanf("%d", &val); 28 | if (i == 1) { 29 | cur_pnode->val = val; 30 | cur_pnode->next = NULL; 31 | } 32 | else { 33 | list_node * new_pnode = new list_node(); 34 | new_pnode->val = val; 35 | new_pnode->next = NULL; 36 | cur_pnode->next = new_pnode; 37 | cur_pnode = new_pnode; 38 | } 39 | } 40 | return phead; 41 | } 42 | 43 | /*--------------------------------------Code Here--------------------------------------*/ 44 | 45 | const int maxn = 2000005; 46 | int hashset[maxn]; 47 | 48 | list_node * remove_rep(list_node * head) 49 | { 50 | memset(hashset, 0, sizeof(hashset)); 51 | list_node* cur = head, *pre = NULL; 52 | while (cur) 53 | { 54 | if (hashset[cur->val + 1000000] == 1) 55 | pre->next = cur->next; 56 | else 57 | { 58 | hashset[cur->val + 1000000] = 1; 59 | pre = cur; 60 | } 61 | cur = cur->next; 62 | } 63 | return head; 64 | } 65 | 66 | 67 | void print_list(list_node * head) 68 | { 69 | while (head != NULL) { 70 | printf("%d ", head->val); 71 | head = head->next; 72 | } 73 | puts(""); 74 | } 75 | 76 | int main () 77 | { 78 | list_node * head = input_list(); 79 | list_node * new_head = remove_rep(head); 80 | print_list(new_head); 81 | return 0; 82 | } -------------------------------------------------------------------------------- /CH2_LinkedList/13b_Delete_Repeat_node.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 删除无序单链表中重复出现的节点 3 | 时间:O(N^2),空间:O(1) 4 | 输入: 5 | 5 6 | 1 3 2 3 1 7 | 输出: 8 | 1 2 3 9 | 注意!!!:本做法因为时间复杂度太高而无法在OJ上通过测试 10 | */ 11 | 12 | 13 | # include 14 | using namespace std; 15 | 16 | struct list_node{ 17 | int val; 18 | struct list_node * next; 19 | }; 20 | 21 | list_node * input_list() 22 | { 23 | int val, n; 24 | scanf("%d", &n); 25 | list_node * phead = new list_node(); 26 | list_node * cur_pnode = phead; 27 | for (int i = 1; i <= n; ++i) { 28 | scanf("%d", &val); 29 | if (i == 1) { 30 | cur_pnode->val = val; 31 | cur_pnode->next = NULL; 32 | } 33 | else { 34 | list_node * new_pnode = new list_node(); 35 | new_pnode->val = val; 36 | new_pnode->next = NULL; 37 | cur_pnode->next = new_pnode; 38 | cur_pnode = new_pnode; 39 | } 40 | } 41 | return phead; 42 | } 43 | 44 | /*--------------------------------------Code Here--------------------------------------*/ 45 | 46 | list_node * remove_rep(list_node * head) 47 | { 48 | list_node* cur = head, *pre = NULL; 49 | int val = cur->val; 50 | while (cur) 51 | { 52 | pre = cur; 53 | list_node* temp = cur->next; 54 | while (temp) 55 | { 56 | if (temp->val == cur->val) 57 | pre->next = temp->next; 58 | else 59 | pre = temp; 60 | temp = temp->next; 61 | } 62 | cur = cur->next; 63 | } 64 | return head; 65 | } 66 | 67 | 68 | void print_list(list_node * head) 69 | { 70 | while (head != NULL) { 71 | printf("%d ", head->val); 72 | head = head->next; 73 | } 74 | puts(""); 75 | } 76 | 77 | int main () 78 | { 79 | list_node * head = input_list(); 80 | list_node * new_head = remove_rep(head); 81 | print_list(new_head); 82 | return 0; 83 | } -------------------------------------------------------------------------------- /CH2_LinkedList/14_Delete_Specify_node.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-11.16 3 | 删除单链表指定值的节点 4 | 时间O(N),空间O(1) 5 | 输入: 6 | 4 7 | 1 2 3 4 8 | 3 9 | 输出: 10 | 1 2 4 11 | */ 12 | 13 | 14 | # include 15 | using namespace std; 16 | 17 | struct list_node{ 18 | int val; 19 | struct list_node * next; 20 | }; 21 | 22 | list_node * input_list() 23 | { 24 | int val, n; 25 | scanf("%d", &n); 26 | list_node * phead = new list_node(); 27 | list_node * cur_pnode = phead; 28 | for (int i = 1; i <= n; ++i) { 29 | scanf("%d", &val); 30 | if (i == 1) { 31 | cur_pnode->val = val; 32 | cur_pnode->next = NULL; 33 | } 34 | else { 35 | list_node * new_pnode = new list_node(); 36 | new_pnode->val = val; 37 | new_pnode->next = NULL; 38 | cur_pnode->next = new_pnode; 39 | cur_pnode = new_pnode; 40 | } 41 | } 42 | return phead; 43 | } 44 | 45 | 46 | /*--------------------------------------Code Here--------------------------------------*/ 47 | 48 | list_node * remove_value(list_node * head, int num) 49 | { 50 | while (head) 51 | { 52 | if (head->val != num) 53 | break; 54 | else 55 | head = head->next; 56 | } 57 | list_node* cur = head, *pre = NULL; 58 | while (cur) 59 | { 60 | if (cur->val == num) 61 | pre->next = cur->next; 62 | else 63 | pre = cur; 64 | cur = cur->next; 65 | } 66 | return head; 67 | } 68 | 69 | void print_list(list_node * head) 70 | { 71 | while (head != NULL) { 72 | printf("%d ", head->val); 73 | head = head->next; 74 | } 75 | puts(""); 76 | } 77 | 78 | int main () 79 | { 80 | list_node * head = input_list(); 81 | int num; 82 | scanf("%d", &num); 83 | list_node * new_head = remove_value(head, num); 84 | print_list(new_head); 85 | return 0; 86 | } -------------------------------------------------------------------------------- /CH2_LinkedList/15a_Tree_List.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-12.7 3 | 将二叉搜索树转换为双向链表 4 | 输入: 5 | 9 6 | 6 4 7 7 | 4 2 5 8 | 2 1 3 9 | 5 0 0 10 | 1 0 0 11 | 3 0 0 12 | 7 0 9 13 | 9 8 0 14 | 8 0 0 15 | 输出: 16 | 1 2 3 4 5 6 7 8 9 17 | */ 18 | 19 | # include 20 | using namespace std; 21 | 22 | struct double_list_node{ 23 | int val; 24 | struct double_list_node * pre, * next; 25 | }; 26 | 27 | struct BST{ 28 | int val; 29 | struct BST * lch, * rch; 30 | }; 31 | 32 | BST * input_BST() 33 | { 34 | int n, fa, lch, rch; 35 | scanf("%d", &n); 36 | BST * root, * new_node; 37 | map mp; // 一个索引对应一个二叉树节点 38 | for (int i = 1; i <= n; ++i) { 39 | scanf("%d %d %d", &fa, &lch, &rch); 40 | if (mp.find(fa) == mp.end()) { 41 | new_node = (BST *)malloc(sizeof(BST)); 42 | mp[fa] = new_node; 43 | new_node->val = fa; 44 | if (i == 1) root = new_node; 45 | } 46 | if (lch && mp.find(lch) == mp.end()) { 47 | new_node = (BST *)malloc(sizeof(BST)); 48 | mp[lch] = new_node; 49 | new_node->val = lch; new_node->lch = new_node->rch = NULL; 50 | } 51 | if (rch && mp.find(rch) == mp.end()) { 52 | new_node = (BST *)malloc(sizeof(BST)); 53 | mp[rch] = new_node; 54 | new_node->val = rch; new_node->lch = new_node->rch = NULL; 55 | } 56 | mp[fa]->lch = (lch ? mp[lch] : NULL); 57 | mp[fa]->rch = (rch ? mp[rch] : NULL); 58 | } 59 | return root; 60 | } 61 | 62 | /*--------------------------------------Code Here--------------------------------------*/ 63 | 64 | queue q; // 队列存储值,供双向链表进行处理 65 | void Inorder(BST* root) 66 | { 67 | if (root == NULL) 68 | return ; 69 | Inorder(root->lch); 70 | q.push(root->val); 71 | Inorder(root->rch); 72 | } 73 | 74 | 75 | double_list_node * convert(BST * root) 76 | { 77 | Inorder(root); 78 | double_list_node* head = new double_list_node(); 79 | 80 | double_list_node* temp_node = head; // 获取移动过程中的前面一个节点 81 | head->val = q.front(); // 获取队首元素 82 | q.pop(); 83 | head->pre = NULL; 84 | head->next = NULL; 85 | while (!q.empty()) 86 | { 87 | double_list_node* node = new double_list_node(); 88 | node->val = q.front(); 89 | q.pop(); 90 | node->pre = temp_node; 91 | temp_node->next = node; 92 | node->next = NULL; 93 | temp_node = node; 94 | } 95 | return head; 96 | } 97 | 98 | void print_double_list(double_list_node * head) 99 | { 100 | while (head != NULL) { 101 | printf("%d ", head->val); 102 | head = head->next; 103 | } 104 | puts(""); 105 | } 106 | 107 | int main () 108 | { 109 | BST * root = input_BST(); 110 | double_list_node * new_double_head = convert(root); 111 | print_double_list(new_double_head); 112 | return 0; 113 | } -------------------------------------------------------------------------------- /CH2_LinkedList/15b_Tree_List.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-12.7 3 | 将二叉搜索树转换为双向链表 4 | 输入: 5 | 9 6 | 6 4 7 7 | 4 2 5 8 | 2 1 3 9 | 5 0 0 10 | 1 0 0 11 | 3 0 0 12 | 7 0 9 13 | 9 8 0 14 | 8 0 0 15 | 输出: 16 | 1 2 3 4 5 6 7 8 9 17 | */ 18 | 19 | # include 20 | using namespace std; 21 | 22 | struct double_list_node{ 23 | int val; 24 | struct double_list_node * pre, * next; 25 | }; 26 | 27 | struct BST{ 28 | int val; 29 | struct BST * lch, * rch; 30 | }; 31 | 32 | BST * input_BST() 33 | { 34 | int n, fa, lch, rch; 35 | scanf("%d", &n); 36 | BST * root, * new_node; 37 | map mp; // 一个索引对应一个二叉树节点 38 | for (int i = 1; i <= n; ++i) { 39 | scanf("%d %d %d", &fa, &lch, &rch); 40 | if (mp.find(fa) == mp.end()) { 41 | new_node = (BST *)malloc(sizeof(BST)); 42 | mp[fa] = new_node; 43 | new_node->val = fa; 44 | if (i == 1) root = new_node; 45 | } 46 | if (lch && mp.find(lch) == mp.end()) { 47 | new_node = (BST *)malloc(sizeof(BST)); 48 | mp[lch] = new_node; 49 | new_node->val = lch; new_node->lch = new_node->rch = NULL; 50 | } 51 | if (rch && mp.find(rch) == mp.end()) { 52 | new_node = (BST *)malloc(sizeof(BST)); 53 | mp[rch] = new_node; 54 | new_node->val = rch; new_node->lch = new_node->rch = NULL; 55 | } 56 | mp[fa]->lch = (lch ? mp[lch] : NULL); 57 | mp[fa]->rch = (rch ? mp[rch] : NULL); 58 | } 59 | return root; 60 | } 61 | 62 | /*--------------------------------------Code Here--------------------------------------*/ 63 | 64 | double_list_node* process(BST* root) // 返回一个双向链表,包含左右指针 65 | { 66 | if (root == NULL) 67 | { 68 | double_list_node* node = new double_list_node(); 69 | node->pre = NULL; 70 | node->next = NULL; 71 | return node; 72 | } 73 | 74 | double_list_node* pre = process(root->pre); 75 | double_list_node* next = process(root->next); 76 | double_list_node* node; 77 | node->val = root->val; 78 | 79 | 80 | } 81 | 82 | void print_double_list(double_list_node * head) 83 | { 84 | while (head != NULL) { 85 | printf("%d ", head->val); 86 | head = head->next; 87 | } 88 | puts(""); 89 | } 90 | 91 | int main () 92 | { 93 | BST * root = input_BST(); 94 | double_list_node * new_double_head = convert(root); 95 | print_double_list(new_double_head); 96 | return 0; 97 | } -------------------------------------------------------------------------------- /CH2_LinkedList/16_Selection_Sort.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-11.23 3 | 单链表的选择排序 4 | 输入: 5 | 5 6 | 1 3 2 4 5 7 | 输出: 8 | 1 2 3 4 5 9 | */ 10 | 11 | # include 12 | using namespace std; 13 | 14 | struct list_node{ 15 | int val; 16 | struct list_node * next; 17 | }; 18 | 19 | 20 | list_node * input_list(void) 21 | { 22 | int n, val; 23 | list_node * phead = new list_node(); 24 | list_node * cur_pnode = phead; 25 | scanf("%d", &n); 26 | for (int i = 1; i <= n; ++i) { 27 | scanf("%d", &val); 28 | if (i == 1) { 29 | cur_pnode->val = val; 30 | cur_pnode->next = NULL; 31 | } 32 | else { 33 | list_node * new_pnode = new list_node(); 34 | new_pnode->val = val; 35 | new_pnode->next = NULL; 36 | cur_pnode->next = new_pnode; 37 | cur_pnode = new_pnode; 38 | } 39 | } 40 | return phead; 41 | } 42 | 43 | /*--------------------------------------Code Here--------------------------------------*/ 44 | 45 | list_node* getSmallestPreNode(list_node* head) 46 | { 47 | list_node *cur = head, *pre = NULL; 48 | list_node *small = head, *pre_small = NULL; 49 | while (cur) 50 | { 51 | if (cur->val < small->val) // small用于对比数值的大小 52 | { 53 | small = cur; 54 | pre_small = pre; 55 | } 56 | pre = cur; 57 | // pre = pre->next; 这样写会段错误, 应该按上一行的表达式 58 | cur = cur->next; 59 | } 60 | return pre_small; 61 | } 62 | 63 | 64 | list_node * selection_sort(list_node * head) // 2 4 5 1 3 --> 1 2 4 5 3 65 | { 66 | list_node *cur = head, *pre = NULL; 67 | list_node *small = NULL, *tail = NULL; 68 | while (cur) 69 | { 70 | pre = getSmallestPreNode(cur); // 获取要最小值节点的前驱 71 | if (pre) // pre非空,即最小的元素不是未排序数组的第一个 72 | { 73 | small = pre->next; 74 | pre->next = small->next; 75 | } 76 | else 77 | small = cur; // pre==NULL 78 | if (tail) // tail非空(已排序的元素不止一个) 79 | { 80 | tail->next = small; 81 | tail = tail->next; 82 | } 83 | else 84 | { 85 | head = small; // 最后返回的地址 86 | tail = small; 87 | } 88 | cur = cur==small ? cur->next : cur; 89 | } 90 | return head; 91 | 92 | } 93 | 94 | 95 | void print_list(list_node * head) 96 | { 97 | while (head != NULL) { 98 | printf("%d ", head->val); 99 | head = head->next; 100 | } 101 | puts(""); 102 | } 103 | 104 | 105 | int main () 106 | { 107 | list_node * head = input_list(); 108 | list_node * new_head = selection_sort(head); 109 | print_list(new_head); 110 | return 0; 111 | } -------------------------------------------------------------------------------- /CH2_LinkedList/17_Delete_tempnode.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-11.23 3 | 一种怪异的链表删除方式 4 | 输入: 5 | 5 6 | 1 2 3 4 5 7 | 3 8 | 输出: 9 | 1 2 4 5 10 | */ 11 | 12 | # include 13 | using namespace std; 14 | 15 | struct list_node{ 16 | int val; 17 | struct list_node * next; 18 | }; 19 | 20 | list_node * find_kth_node(list_node * head, int k) 21 | { 22 | list_node * c = head; 23 | for (int i = 1; i < k; ++i) c = c->next; 24 | return c; 25 | } 26 | 27 | list_node * input_list(void) 28 | { 29 | int n, val; 30 | list_node * phead = new list_node(); 31 | list_node * cur_pnode = phead; 32 | scanf("%d", &n); 33 | for (int i = 1; i <= n; ++i) { 34 | scanf("%d", &val); 35 | if (i == 1) { 36 | cur_pnode->val = val; 37 | cur_pnode->next = NULL; 38 | } 39 | else { 40 | list_node * new_pnode = new list_node(); 41 | new_pnode->val = val; 42 | new_pnode->next = NULL; 43 | cur_pnode->next = new_pnode; 44 | cur_pnode = new_pnode; 45 | } 46 | } 47 | return phead; 48 | } 49 | 50 | /*--------------------------------------Code Here--------------------------------------*/ 51 | 52 | void remove_node_wired(list_node * node) 53 | { 54 | list_node *next = node->next; 55 | node->val = next->val; 56 | node->next = next->next; 57 | } 58 | 59 | 60 | void print_list(list_node * head) 61 | { 62 | while (head != NULL) { 63 | printf("%d ", head->val); 64 | head = head->next; 65 | } 66 | puts(""); 67 | } 68 | 69 | 70 | int main () 71 | { 72 | list_node * head = input_list(); 73 | int n; 74 | scanf("%d", &n); 75 | list_node * node = find_kth_node(head, n); 76 | remove_node_wired(node); 77 | print_list(head); 78 | return 0; 79 | } -------------------------------------------------------------------------------- /CH2_LinkedList/18_Circular_List_Insert.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-11.23 3 | 向有序环形单链表中插入元素 4 | 输入: 5 | 5 6 | 1 2 3 4 5 7 | 6 8 | 输出: 9 | 1 2 3 4 5 6 10 | */ 11 | # include 12 | using namespace std; 13 | 14 | struct list_node{ 15 | int val; 16 | struct list_node * next; 17 | }; 18 | 19 | 20 | list_node * input_list(void) 21 | { 22 | int n, val; 23 | list_node * phead = new list_node(); 24 | list_node * cur_pnode = phead; 25 | scanf("%d", &n); 26 | for (int i = 1; i <= n; ++i) { 27 | scanf("%d", &val); 28 | if (i == 1) { 29 | cur_pnode->val = val; 30 | cur_pnode->next = NULL; 31 | } 32 | else { 33 | list_node * new_pnode = new list_node(); 34 | new_pnode->val = val; 35 | new_pnode->next = NULL; 36 | cur_pnode->next = new_pnode; 37 | cur_pnode = new_pnode; 38 | if (i == n) { 39 | new_pnode->next = phead; 40 | } 41 | } 42 | } 43 | return phead; 44 | } 45 | 46 | /*--------------------------------------Code Here--------------------------------------*/ 47 | 48 | list_node * insert_num(list_node * head, int num) 49 | { 50 | list_node *pre = head; 51 | list_node *cur = head; 52 | while (pre->next != head) 53 | pre = pre->next; // 找到末尾节点(头结点的前驱) 54 | while (1) 55 | { 56 | if (cur->val > num) // 插入头部或中部(头部需要多加一步) 57 | { 58 | list_node *node = new list_node(); 59 | node->val = num; 60 | pre->next = node; 61 | node->next = cur; 62 | if (cur == head) // 在显示时默认显示在最后,需要做一步调整 63 | head = node; 64 | break; 65 | } 66 | pre = cur; 67 | cur = cur->next; 68 | if (cur == head) // 插入末尾 69 | { 70 | list_node *node = new list_node(); 71 | node->val = num; 72 | pre->next = node; 73 | node->next = cur; 74 | break; 75 | } 76 | } 77 | return head; 78 | } 79 | 80 | 81 | void print_list(list_node * head) 82 | { 83 | list_node * h = head; 84 | while (1) { 85 | printf("%d ", head->val); 86 | if (head->next == h) break; 87 | head = head->next; 88 | } 89 | puts(""); 90 | } 91 | 92 | 93 | int main () 94 | { 95 | list_node * head = input_list(); 96 | int n; 97 | scanf("%d", &n); 98 | list_node * new_head = insert_num(head, n); 99 | print_list(new_head); 100 | return 0; 101 | } -------------------------------------------------------------------------------- /CH2_LinkedList/19_Merge_2List.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-11.30 3 | 合并两个有序链表 4 | 输入: 5 | 5 6 | 1 2 3 4 5 7 | 6 8 | 7 8 9 10 11 12 9 | 输出: 10 | 1 2 3 4 5 7 8 9 10 11 12 11 | */ 12 | 13 | # include 14 | using namespace std; 15 | 16 | struct list_node{ 17 | int val; 18 | struct list_node * next; 19 | }; 20 | 21 | 22 | list_node * input_list(void) 23 | { 24 | int n, val; 25 | list_node * phead = new list_node(); 26 | list_node * cur_pnode = phead; 27 | scanf("%d", &n); 28 | for (int i = 1; i <= n; ++i) { 29 | scanf("%d", &val); 30 | if (i == 1) { 31 | cur_pnode->val = val; 32 | cur_pnode->next = NULL; 33 | } 34 | else { 35 | list_node * new_pnode = new list_node(); 36 | new_pnode->val = val; 37 | new_pnode->next = NULL; 38 | cur_pnode->next = new_pnode; 39 | cur_pnode = new_pnode; 40 | } 41 | } 42 | return phead; 43 | } 44 | 45 | /*--------------------------------------Code Here--------------------------------------*/ 46 | 47 | list_node * merge_list(list_node * head1, list_node * head2) 48 | { 49 | list_node *head = head1->val < head2->val ? head1 : head2; 50 | list_node *cur1 = head==head1 ? head1 : head2; // 记录小的--主线 51 | list_node *cur2 = head==head1 ? head2 : head1; 52 | list_node *pre = NULL; 53 | while (cur1 && cur2) // 有一个为空就退出 54 | { 55 | if (cur1->val < cur2->val) 56 | { 57 | pre = cur1; // pre指向当前当前变化的前一个,1<2,故接着1 58 | cur1 = cur1->next; 59 | } 60 | else 61 | { 62 | //list_node *next = cur1->next; 63 | list_node *next = cur2->next; 64 | pre->next = cur2; 65 | cur2->next = cur1; 66 | pre = cur2; // pre现在才是cur2,此时cur2next = cur1 ? cur1 : cur2; // 哪个非空跟哪个 72 | return head; 73 | } 74 | 75 | 76 | void print_list(list_node * head) 77 | { 78 | while (head != NULL) { 79 | printf("%d ", head->val); 80 | head = head->next; 81 | } 82 | puts(""); 83 | } 84 | 85 | 86 | int main () 87 | { 88 | list_node * head1 = input_list(); 89 | list_node * head2 = input_list(); 90 | list_node * new_head = merge_list(head1, head2); 91 | print_list(new_head); 92 | return 0; 93 | } -------------------------------------------------------------------------------- /CH2_LinkedList/1_Overlap_List.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-10.17 3 | CH2 链表--打印两个有序链表的公共部分 4 | 输入: 5 | 4 6 | 1 2 3 4 7 | 5 8 | 1 2 3 5 6 9 | 输出: 10 | 1 2 3 11 | */ 12 | 13 | # include 14 | using namespace std; 15 | 16 | struct list_node{ 17 | int val; 18 | struct list_node * next; 19 | }; //链表的节点 20 | 21 | list_node * input_list(void) //读入链表 22 | { 23 | int n, val; 24 | list_node * phead = new list_node(); 25 | list_node * cur_pnode = phead; 26 | scanf("%d", &n); 27 | for (int i = 1; i <= n; ++i) { 28 | scanf("%d", &val); 29 | if (i == 1) { 30 | cur_pnode->val = val; 31 | cur_pnode->next = NULL; 32 | } 33 | else { 34 | list_node * new_pnode = new list_node(); 35 | new_pnode->val = val; 36 | new_pnode->next = NULL; 37 | cur_pnode->next = new_pnode; 38 | cur_pnode = new_pnode; 39 | } 40 | } 41 | return phead; 42 | } 43 | 44 | //------------------------------------------Code Here-------------------------------------------// 45 | void sol(list_node * a_head, list_node * b_head) 46 | { 47 | //////在下面完成代码 48 | while (a_head && b_head) 49 | { 50 | if (a_head->val == b_head->val) 51 | { 52 | cout << a_head->val << " "; 53 | a_head = a_head->next; 54 | b_head = b_head->next; 55 | } 56 | else if (a_head == NULL || a_head->val > b_head->val) 57 | b_head = b_head->next; 58 | else 59 | a_head = a_head->next; 60 | } 61 | } 62 | 63 | int main () 64 | { 65 | list_node * a_head = input_list(); // A 链表的头节点 66 | list_node * b_head = input_list(); // B 链表的头节点 67 | sol(a_head, b_head); 68 | return 0; 69 | } -------------------------------------------------------------------------------- /CH2_LinkedList/20_Left_RightMerge.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-11.30 3 | 按左右半区的方式重新组合单链表 4 | 输入: 5 | 6 6 | 1 2 3 4 5 6 7 | 输出: 8 | 1 4 2 5 3 6 9 | */ 10 | 11 | # include 12 | using namespace std; 13 | 14 | struct list_node{ 15 | int val; 16 | struct list_node * next; 17 | }; 18 | 19 | 20 | list_node * input_list(void) 21 | { 22 | int n, val; 23 | list_node * phead = new list_node(); 24 | list_node * cur_pnode = phead; 25 | scanf("%d", &n); 26 | for (int i = 1; i <= n; ++i) { 27 | scanf("%d", &val); 28 | if (i == 1) { 29 | cur_pnode->val = val; 30 | cur_pnode->next = NULL; 31 | } 32 | else { 33 | list_node * new_pnode = new list_node(); 34 | new_pnode->val = val; 35 | new_pnode->next = NULL; 36 | cur_pnode->next = new_pnode; 37 | cur_pnode = new_pnode; 38 | } 39 | } 40 | return phead; 41 | } 42 | 43 | /*--------------------------------------Code Here--------------------------------------*/ 44 | 45 | list_node * relocate(list_node * head) 46 | { 47 | list_node *last_left = head, *last = head->next; 48 | while (last->next && last->next->next) // 处心积虑 49 | { 50 | last = last->next->next; 51 | last_left = last_left->next; 52 | } 53 | // last_left是左半边最末端的一个 54 | list_node *left = head, *right = last_left->next; 55 | last_left->next = NULL; 56 | while (left && right) // 左侧和右侧都非空时进入循环 57 | { 58 | list_node *next_left = left->next; // 1 2 3 vs 4 5 6 --> 1 4 2 3 vs 5 6 59 | list_node *next_right = right->next; 60 | left->next = right; 61 | if (next_left) 62 | right->next = next_left; 63 | right = next_right; 64 | left = next_left; 65 | } 66 | return head; 67 | } 68 | 69 | 70 | void print_list(list_node * head) 71 | { 72 | while (head != NULL) { 73 | printf("%d ", head->val); 74 | head = head->next; 75 | } 76 | puts(""); 77 | } 78 | 79 | 80 | int main () 81 | { 82 | list_node * head = input_list(); 83 | list_node * new_head = relocate(head); 84 | print_list(new_head); 85 | return 0; 86 | } -------------------------------------------------------------------------------- /CH2_LinkedList/2_Delete_Lastk.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-10.19 3 | CH2 链表--删除链表倒数第k个节点 4 | 输入: 5 | 5 4 6 | 1 2 3 4 5 7 | 8 | 输出: 9 | 1 3 4 5 10 | */ 11 | 12 | # include 13 | using namespace std; 14 | 15 | struct list_node{ 16 | int val; 17 | struct list_node * next; 18 | }; //链表的节点 19 | 20 | int K; 21 | 22 | list_node * input_list(void) //读入链表 23 | { 24 | int n, val; 25 | list_node * phead = new list_node(); 26 | list_node * cur_pnode = phead; 27 | scanf("%d %d", &n, &K); 28 | for (int i = 1; i <= n; ++i) { 29 | scanf("%d", &val); 30 | if (i == 1) { 31 | cur_pnode->val = val; 32 | cur_pnode->next = NULL; 33 | } 34 | else { 35 | list_node * new_pnode = new list_node(); 36 | new_pnode->val = val; 37 | new_pnode->next = NULL; 38 | cur_pnode->next = new_pnode; 39 | cur_pnode = new_pnode; 40 | } 41 | } 42 | return phead; 43 | } 44 | 45 | //------------------------------------------Code Here-------------------------------------------// 46 | list_node * remove_last_kth_node(list_node * head, int K) 47 | { 48 | //////在下面完成代码 49 | int len = 0; 50 | list_node* p = head; 51 | while (p) // 计算链表长度 52 | { 53 | len++; 54 | p = p->next; 55 | } 56 | p = head; 57 | for (int i = 1; i <= len && p; i++) // 遍历链表找len-K的位置,注意判断条件 58 | { 59 | if (i == len - K) 60 | { 61 | list_node* next_node = p->next; 62 | p->next = next_node->next; 63 | } 64 | p = p-> next; 65 | } 66 | return head; 67 | } 68 | 69 | void print_list(list_node * head) 70 | { 71 | while (head != NULL) { 72 | printf("%d ", head->val); 73 | head = head->next; 74 | } 75 | } 76 | 77 | int main () 78 | { 79 | freopen("in.txt", "r", stdin); 80 | list_node * head = input_list(); // 链表的头节点 81 | list_node * rhead = remove_last_kth_node(head, K); 82 | print_list(rhead); 83 | return 0; 84 | } -------------------------------------------------------------------------------- /CH2_LinkedList/3_Delete_Medium.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-10.19 3 | CH2 链表--删除链表倒数第k个节点 4 | 输入: 5 | 5 6 | 1 2 3 4 5 7 | 8 | 输出: 9 | 1 2 4 5 10 | */ 11 | 12 | # include 13 | using namespace std; 14 | 15 | struct list_node{ 16 | int val; 17 | struct list_node * next; 18 | }; //链表的节点 19 | 20 | 21 | list_node * input_list(void) //读入链表 22 | { 23 | int n, val; 24 | list_node * phead = new list_node(); 25 | list_node * cur_pnode = phead; 26 | scanf("%d", &n); 27 | for (int i = 1; i <= n; ++i) { 28 | scanf("%d", &val); 29 | if (i == 1) { 30 | cur_pnode->val = val; 31 | cur_pnode->next = NULL; 32 | } 33 | else { 34 | list_node * new_pnode = new list_node(); 35 | new_pnode->val = val; 36 | new_pnode->next = NULL; 37 | cur_pnode->next = new_pnode; 38 | cur_pnode = new_pnode; 39 | } 40 | } 41 | return phead; 42 | } 43 | 44 | //------------------------------------------Code Here-------------------------------------------// 45 | list_node * remove_last_kth_node(list_node * head) 46 | { 47 | //////在下面完成代码 48 | if (head == NULL || head->next == NULL) 49 | return NULL; 50 | if (head->next->next == NULL) 51 | return head->next; 52 | list_node* pre = head, *cur = head->next->next; 53 | while (cur->next && cur->next->next) // 必须有cur->next这个判断,否则段错误,因为NULL没有next指针,访问错误 54 | { 55 | pre = pre->next; 56 | cur = cur->next->next; 57 | } 58 | pre->next = pre->next->next; 59 | return head; 60 | } 61 | 62 | void print_list(list_node * head) 63 | { 64 | while (head != NULL) { 65 | printf("%d ", head->val); 66 | head = head->next; 67 | } 68 | } 69 | 70 | int main () 71 | { 72 | freopen("in.txt", "r", stdin); 73 | list_node * head = input_list(); // 链表的头节点 74 | list_node * rhead = remove_last_kth_node(head); 75 | print_list(rhead); 76 | return 0; 77 | } -------------------------------------------------------------------------------- /CH2_LinkedList/4_Reverse_LinkedList.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-10.19 3 | CH2 链表--反转单双链表 4 | 输入: 5 | 3 6 | 1 2 3 7 | 4 8 | 1 2 3 4 9 | 10 | 输出: 11 | 3 2 1 12 | 4 3 2 1 13 | */ 14 | 15 | # include 16 | using namespace std; 17 | 18 | struct list_node{ 19 | int val; 20 | struct list_node * next; 21 | }; 22 | struct double_list_node{ 23 | int val; 24 | struct double_list_node * pre, * next; 25 | }; 26 | 27 | list_node * input_list(void) 28 | { 29 | int n, val; 30 | list_node * phead = new list_node(); 31 | list_node * cur_pnode = phead; 32 | scanf("%d", &n); 33 | for (int i = 1; i <= n; ++i) { 34 | scanf("%d", &val); 35 | if (i == 1) { 36 | cur_pnode->val = val; 37 | cur_pnode->next = NULL; 38 | } 39 | else { 40 | list_node * new_pnode = new list_node(); 41 | new_pnode->val = val; 42 | new_pnode->next = NULL; 43 | cur_pnode->next = new_pnode; 44 | cur_pnode = new_pnode; 45 | } 46 | } 47 | return phead; 48 | } 49 | 50 | double_list_node * input_double_list(void) 51 | { 52 | int n, val; 53 | double_list_node * phead = new double_list_node(); 54 | double_list_node * cur_pnode = phead; 55 | scanf("%d", &n); 56 | for (int i = 1; i <= n; ++i) { 57 | scanf("%d", &val); 58 | if (i == 1) { 59 | cur_pnode->val = val; 60 | cur_pnode->next = NULL; 61 | cur_pnode->pre = NULL; 62 | } 63 | else { 64 | double_list_node * new_pnode = new double_list_node(); 65 | new_pnode->val = val; 66 | new_pnode->next = NULL; 67 | new_pnode->pre = cur_pnode; 68 | cur_pnode->next = new_pnode; 69 | cur_pnode = new_pnode; 70 | } 71 | } 72 | return phead; 73 | } 74 | 75 | //---------------------------------------Code Here------------------------------------------// 76 | list_node * reverse_list(list_node * head) 77 | { 78 | //////在下面完成代码 79 | if (head->next == NULL) 80 | return head; 81 | list_node* pre = NULL, *cur = head; // 对pre进行修改 82 | list_node* next = cur->next; 83 | while (next) 84 | { 85 | cur->next = pre; 86 | pre = cur; 87 | cur = next; 88 | next = next->next; 89 | } 90 | cur->next = pre; 91 | return cur; 92 | } 93 | 94 | double_list_node * reverse_double_list(double_list_node * head) 95 | { 96 | //////在下面完成代码 97 | double_list_node* pre = NULL, *next = NULL; 98 | while (head) 99 | { 100 | next = head->next; // 不事先定义位置,进入循环后定义 101 | head->next = pre; 102 | head->pre = next; 103 | // next = pre->pre; 104 | pre = head; 105 | head = next; 106 | } 107 | return pre; 108 | 109 | } 110 | 111 | void print_list(list_node * head) 112 | { 113 | while (head != NULL) { 114 | printf("%d ", head->val); 115 | head = head->next; 116 | } 117 | puts(""); 118 | } 119 | 120 | void print_double_list(double_list_node * head) 121 | { 122 | while (head != NULL) { 123 | printf("%d ", head->val); 124 | head = head->next; 125 | } 126 | puts(""); 127 | } 128 | 129 | int main () 130 | { 131 | // freopen("in.txt", "r", stdin); 132 | list_node * head = input_list(); 133 | double_list_node * double_head = input_double_list(); 134 | list_node * new_head = reverse_list(head); 135 | double_list_node * new_double_head = reverse_double_list(double_head); 136 | print_list(new_head); 137 | print_double_list(new_double_head); 138 | return 0; 139 | } -------------------------------------------------------------------------------- /CH2_LinkedList/5_Reverse_SubLinkedList.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-10.21 3 | CH2 链表--反转部分链表 4 | 输入: 5 | 5 6 | 1 2 3 4 5 7 | 1 3 8 | 输出: 9 | 3 2 1 4 5 10 | */ 11 | 12 | # include 13 | using namespace std; 14 | 15 | struct list_node{ 16 | int val; 17 | struct list_node * next; 18 | }; 19 | 20 | list_node * input_list(void) 21 | { 22 | int n, val; 23 | list_node * phead = new list_node(); 24 | list_node * cur_pnode = phead; 25 | scanf("%d", &n); 26 | for (int i = 1; i <= n; ++i) { 27 | scanf("%d", &val); 28 | if (i == 1) { 29 | cur_pnode->val = val; 30 | cur_pnode->next = NULL; 31 | } 32 | else { 33 | list_node * new_pnode = new list_node(); 34 | new_pnode->val = val; 35 | new_pnode->next = NULL; 36 | cur_pnode->next = new_pnode; 37 | cur_pnode = new_pnode; 38 | } 39 | } 40 | return phead; 41 | } 42 | 43 | /*----------------------------------------Code Here-------------------------------------*/ 44 | list_node * reverse_list(list_node * head, int L, int R) 45 | { 46 | //////在下面完成代码,分两种情况---反转包括头部和不包括头部 47 | list_node* node1 = head; 48 | int cnt = 0; 49 | list_node* fpre = NULL, *tpos = NULL; 50 | while (node1) 51 | { 52 | cnt++; 53 | fpre = cnt==L-1 ? node1 : fpre; 54 | tpos = cnt==R+1 ? node1 : tpos; 55 | node1 = node1->next; 56 | } 57 | 58 | node1 = fpre==NULL ? head : fpre->next; // 需要掉顺序的头结点,但不是返回的头结点 59 | list_node* node2 = node1->next; 60 | node1->next = tpos; 61 | list_node* node3 = NULL; // 先定义为NULL 62 | while (node2 != tpos) 63 | { 64 | node3 = node2->next; 65 | node2->next = node1; 66 | node1 = node2; 67 | node2 = node3; 68 | } 69 | if (fpre == NULL) 70 | return node1; 71 | else // 头结点不需要逆序时,多一步,即将逆序点前一位的节点指向node1 72 | { 73 | fpre->next = node1; 74 | return head; 75 | } 76 | } 77 | 78 | void print_list(list_node * head) 79 | { 80 | while (head != NULL) { 81 | printf("%d ", head->val); 82 | head = head->next; 83 | } 84 | puts(""); 85 | } 86 | 87 | 88 | int main () 89 | { 90 | int L, R; 91 | list_node * head = input_list(); 92 | scanf("%d%d", &L, &R); 93 | list_node * new_head = reverse_list(head, L, R); 94 | print_list(new_head); 95 | return 0; 96 | } -------------------------------------------------------------------------------- /CH2_LinkedList/6a_Joseph.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-10.21 3 | CH2 链表--约瑟夫问题--基础,这一题需要读者自己创建循环链表!!! 4 | 输入: 5 | 5 2 6 | 输出: 7 | 3 8 | */ 9 | 10 | #include 11 | #include 12 | using namespace std; 13 | 14 | struct circular_list // 循环链表:结构体内容与单链表相同,但操作不同 15 | { 16 | int val; 17 | circular_list* next; 18 | }; 19 | 20 | 21 | circular_list* input_list(int n) 22 | { 23 | circular_list* head = new circular_list(); // 局部变量使用栈区存储,动态变量为堆区存储 24 | circular_list* cur = head; 25 | for (int i = 1; i <= n; i++) 26 | { 27 | if (i == 1) 28 | cur->val = i; 29 | else 30 | { 31 | circular_list* temp = new circular_list(); 32 | temp->val = i; 33 | cur->next = temp; 34 | cur = cur->next; 35 | } 36 | } 37 | cur->next = head; 38 | return head; 39 | } 40 | 41 | //------------------------------------------Code Here-------------------------------------------// 42 | void Joseph(circular_list* head, int num) // 报数到num个人删除一次 43 | { 44 | int cnt = 0; 45 | circular_list* last = head; 46 | while (last->next != head) 47 | last = last->next; 48 | while (last != head) 49 | { 50 | cnt++; 51 | if (cnt == num) // 删除当前节点 52 | { 53 | last->next = head->next; 54 | cnt = 0; 55 | } 56 | else 57 | last = last->next; 58 | head = head->next; 59 | } 60 | cout << head->val; 61 | } 62 | 63 | 64 | void print_list(circular_list* head) 65 | { 66 | circular_list* cur = head; 67 | do 68 | { 69 | cout << cur->val << " "; 70 | cur = cur->next; 71 | }while(cur != head); 72 | } 73 | 74 | int main() 75 | { 76 | int n, num; 77 | cin >> n >> num; 78 | circular_list* list = input_list(n); 79 | Joseph(list, num); 80 | 81 | return 0; 82 | } -------------------------------------------------------------------------------- /CH2_LinkedList/6b_Joseph.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | int n, m, new_num; 8 | cin >> n >> m; 9 | int last = 1; 10 | for (int i = 2; i <= n; i++) 11 | { 12 | new_num = (last+m-1)%i+1; // 注意m是报到num就自杀 13 | last = new_num; 14 | } 15 | cout << last; 16 | return 0; 17 | } -------------------------------------------------------------------------------- /CH2_LinkedList/7a1_Palindrome.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-10.25 3 | CH2 链表--判断链表是否是回文结构 4 | 输入: 5 | 4 6 | 1 2 2 1 7 | 8 | 输出: 9 | true 10 | */ 11 | 12 | # include 13 | using namespace std; 14 | 15 | struct list_node{ 16 | int val; 17 | struct list_node * next; 18 | }; 19 | 20 | list_node * input_list(void) 21 | { 22 | int n, val; 23 | list_node * phead = new list_node(); 24 | list_node * cur_pnode = phead; 25 | scanf("%d", &n); 26 | for (int i = 1; i <= n; ++i) { 27 | scanf("%d", &val); 28 | if (i == 1) { 29 | cur_pnode->val = val; 30 | cur_pnode->next = NULL; 31 | } 32 | else { 33 | list_node * new_pnode = new list_node(); 34 | new_pnode->val = val; 35 | new_pnode->next = NULL; 36 | cur_pnode->next = new_pnode; 37 | cur_pnode = new_pnode; 38 | } 39 | } 40 | return phead; 41 | } 42 | 43 | 44 | //------------------------------------------Code Here-------------------------------------------// 45 | list_node * check(list_node * head) // 时间复杂度O(2n),空间复杂度O(n) 46 | { 47 | //////在下面完成代码 48 | list_node* cur = head; 49 | stack s; 50 | while (cur) 51 | { 52 | s.push(cur->val); 53 | cur = cur->next; 54 | } 55 | 56 | cur = head; 57 | while (!s.empty()) 58 | { 59 | if (s.top() != cur->val) 60 | { 61 | cout << "false"; 62 | return head; 63 | } 64 | s.pop(); 65 | cur = cur->next; 66 | } 67 | 68 | cout << "true"; 69 | return head; 70 | 71 | } 72 | 73 | 74 | int main () 75 | { 76 | int L, R; 77 | list_node * head = input_list(); 78 | check(head); 79 | return 0; 80 | } -------------------------------------------------------------------------------- /CH2_LinkedList/7a2_Palindrome.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-10.25 3 | CH2 链表--判断链表是否是回文结构 4 | 输入: 5 | 4 6 | 1 2 2 1 7 | 8 | 输出: 9 | true 10 | */ 11 | 12 | # include 13 | using namespace std; 14 | 15 | struct list_node{ 16 | int val; 17 | struct list_node * next; 18 | }; 19 | 20 | list_node * input_list(void) 21 | { 22 | int n, val; 23 | list_node * phead = new list_node(); 24 | list_node * cur_pnode = phead; 25 | scanf("%d", &n); 26 | for (int i = 1; i <= n; ++i) { 27 | scanf("%d", &val); 28 | if (i == 1) { 29 | cur_pnode->val = val; 30 | cur_pnode->next = NULL; 31 | } 32 | else { 33 | list_node * new_pnode = new list_node(); 34 | new_pnode->val = val; 35 | new_pnode->next = NULL; 36 | cur_pnode->next = new_pnode; 37 | cur_pnode = new_pnode; 38 | } 39 | } 40 | return phead; 41 | } 42 | 43 | //---------------------------------------Code Here----------------------------------------// 44 | 45 | list_node * check(list_node * head) // 时间复杂度O(3n/2),空间复杂度O(n/2) 46 | { 47 | //////在下面完成代码 48 | list_node* cur = head, *cur2 = head->next; 49 | stack s; 50 | while (cur2 && cur2->next) // 找到中间节点(跳跃指针) 51 | { 52 | // s.push(cur->) 53 | cur = cur->next; 54 | cur2 = cur2->next->next; 55 | } 56 | 57 | cur = cur->next; // 将右半边加入栈 58 | while (cur) 59 | { 60 | s.push(cur->val); 61 | cur = cur->next; 62 | } 63 | cur = head; 64 | 65 | while (!s.empty()) // 将栈与左半边元素进行配对比较 66 | { 67 | if (s.top() != cur->val) 68 | { 69 | cout << "false"; 70 | return head; 71 | } 72 | s.pop(); 73 | cur = cur->next; 74 | } 75 | cout << "true"; 76 | return head; 77 | } 78 | 79 | 80 | int main () 81 | { 82 | int L, R; 83 | list_node * head = input_list(); 84 | check(head); 85 | return 0; 86 | } -------------------------------------------------------------------------------- /CH2_LinkedList/7b_Palindrome.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-10.27 3 | CH2 链表--判断链表是否是回文结构 4 | 输入: 5 | 4 6 | 1 2 2 1 7 | 8 | 输出: 9 | true 10 | */ 11 | # include 12 | using namespace std; 13 | 14 | struct list_node{ 15 | int val; 16 | struct list_node * next; 17 | }; 18 | 19 | list_node * input_list(void) 20 | { 21 | int n, val; 22 | list_node * phead = new list_node(); 23 | list_node * cur_pnode = phead; 24 | scanf("%d", &n); 25 | for (int i = 1; i <= n; ++i) { 26 | scanf("%d", &val); 27 | if (i == 1) { 28 | cur_pnode->val = val; 29 | cur_pnode->next = NULL; 30 | } 31 | else { 32 | list_node * new_pnode = new list_node(); 33 | new_pnode->val = val; 34 | new_pnode->next = NULL; 35 | cur_pnode->next = new_pnode; 36 | cur_pnode = new_pnode; 37 | } 38 | } 39 | return phead; 40 | } 41 | 42 | 43 | //------------------------------------------Code Here-------------------------------------------// 44 | list_node * check(list_node * head) 45 | { 46 | //////在下面完成代码 47 | list_node* subhead = head; // subhead:后半边的头节点(开始进行反转) 48 | list_node* last = head; 49 | list_node* node_front = NULL; // 追随subhead的前一个节点 50 | while (last && last->next) 51 | { 52 | node_front = subhead; 53 | subhead = subhead->next; 54 | last = last->next->next; 55 | } 56 | // 此时已经找到了subhead 57 | // subhead->next = NULL; 58 | list_node* node = subhead; 59 | list_node* node_last = NULL; // 60 | while (node) // 反转后半部分链表 61 | { 62 | node_last = node->next; 63 | node->next = node_front; 64 | node_front = node; 65 | node = node_last; 66 | } 67 | subhead->next = NULL; 68 | // 此时node_front是单链表的末尾节点 69 | list_node* first_half = head; 70 | list_node* second_half = node_front; 71 | int ok = 1; 72 | while (first_half && second_half) 73 | { 74 | if (first_half->val != second_half->val) 75 | { 76 | ok = 0; 77 | cout << "false"; 78 | break; 79 | } 80 | first_half = first_half->next; 81 | second_half = second_half->next; 82 | } 83 | if (ok) 84 | cout << "true"; 85 | // 使用node_front, node_last, node进行后半部分反转 86 | node = node_front; // 指向最后一个节点 87 | while (node) 88 | { 89 | node_front = node_front->next; 90 | node->next = node_last; 91 | node_last = node; 92 | node = node_front; 93 | } 94 | return head; 95 | } 96 | 97 | 98 | 99 | void print_list(list_node * head) 100 | { 101 | while (head != NULL) { 102 | printf("%d ", head->val); 103 | head = head->next; 104 | } 105 | } 106 | 107 | int main () 108 | { 109 | int L, R; 110 | list_node * head = input_list(); 111 | check(head); 112 | // print_list(head); 113 | return 0; 114 | } -------------------------------------------------------------------------------- /CH2_LinkedList/8a_Partition.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-10.27 3 | CH2 链表--将单链表按某值划分成左边小、中间相等、右边大的形式 4 | 时间复杂度O(N),空间复杂度O(N) 5 | 6 | 输入: 7 | 6 3 8 | 3 3 3 4 5 1 9 | 输出: 10 | 1 3 3 3 5 4 11 | */ 12 | 13 | # include 14 | using namespace std; 15 | 16 | struct list_node{ 17 | int val; 18 | struct list_node * next; 19 | }; 20 | 21 | int pivot; 22 | const int maxn = 1000005; 23 | int arr[maxn]; 24 | 25 | list_node * input_list(void) 26 | { 27 | int n, val; 28 | list_node * phead = new list_node(); 29 | list_node * cur_pnode = phead; 30 | scanf("%d%d", &n, &pivot); 31 | for (int i = 1; i <= n; ++i) { 32 | scanf("%d", &val); 33 | if (i == 1) { 34 | cur_pnode->val = val; 35 | cur_pnode->next = NULL; 36 | } 37 | else { 38 | list_node * new_pnode = new list_node(); 39 | new_pnode->val = val; 40 | new_pnode->next = NULL; 41 | cur_pnode->next = new_pnode; 42 | cur_pnode = new_pnode; 43 | } 44 | } 45 | return phead; 46 | } 47 | 48 | //------------------------------------------Code Here-------------------------------------------// 49 | void swap(int arr[], int a, int b) 50 | { 51 | int t = arr[a]; 52 | arr[a] = arr[b]; 53 | arr[b] = t; 54 | } 55 | 56 | void arrPartition(int arr[], int pivot, int len) 57 | { 58 | int small = -1, big = len, ind = 0; 59 | while (ind != big) 60 | { 61 | if (arr[ind] == pivot) 62 | ind++; 63 | else if (arr[ind] < pivot) 64 | // 此时有两种情况: case1--ind比small大1位,case2--ind比small大多位,中间全部是pivot(3 3 3 1 4 5)中的1 65 | swap(arr, ++small, ind++); // 用small+1与ind交换,将val; 81 | cur = cur->next; 82 | } 83 | arrPartition(arr, pivot, len); 84 | cur = head; 85 | len = 0; 86 | while (cur) 87 | { 88 | cur->val = arr[len++]; 89 | cur = cur->next; 90 | } 91 | return head; 92 | } 93 | 94 | void print_list(list_node * head) 95 | { 96 | while (head != NULL) { 97 | printf("%d ", head->val); 98 | head = head->next; 99 | } 100 | } 101 | 102 | 103 | int main () 104 | { 105 | list_node * head = input_list(); 106 | head = list_partition(head, pivot); 107 | print_list(head); 108 | return 0; 109 | } -------------------------------------------------------------------------------- /CH2_LinkedList/8b_Partition.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-10.27 3 | CH2 链表--将单链表按某值划分成左边小、中间相等、右边大的形式 4 | 时间复杂度O(N),空间复杂度O(N) 5 | 6 | 输入: 7 | 7 5 8 | 7 9 1 8 5 2 5 9 | 输出: 10 | 1 2 5 5 7 9 8 11 | */ 12 | 13 | # include 14 | using namespace std; 15 | 16 | struct list_node{ 17 | int val; 18 | struct list_node * next; 19 | }; 20 | 21 | int pivot; 22 | const int maxn = 1000005; 23 | int arr[maxn]; 24 | 25 | list_node * input_list(void) 26 | { 27 | int n, val; 28 | list_node * phead = new list_node(); 29 | list_node * cur_pnode = phead; 30 | scanf("%d%d", &n, &pivot); 31 | for (int i = 1; i <= n; ++i) { 32 | scanf("%d", &val); 33 | if (i == 1) { 34 | cur_pnode->val = val; 35 | cur_pnode->next = NULL; 36 | } 37 | else { 38 | list_node * new_pnode = new list_node(); 39 | new_pnode->val = val; 40 | new_pnode->next = NULL; 41 | cur_pnode->next = new_pnode; 42 | cur_pnode = new_pnode; 43 | } 44 | } 45 | return phead; 46 | } 47 | 48 | //------------------------------------------Code Here-------------------------------------------// 49 | 50 | list_node * list_partition(list_node * head, int pivot) 51 | { 52 | //////在下面完成代码,注:arr[]在全局处定义 53 | list_node* sH = NULL, *sL = NULL; 54 | list_node* eH = NULL, *eL = NULL; 55 | list_node* bH = NULL, *bL = NULL; 56 | while (head) 57 | { 58 | if (head->val < pivot) 59 | { 60 | if (sH == NULL) 61 | { 62 | sH = head; // 两个都要更新 63 | sL = head; 64 | } 65 | else 66 | { 67 | sL->next = head; 68 | sL = sL->next; // 注意要更新 69 | } 70 | } 71 | else if (head->val == pivot) 72 | { 73 | if (eH == NULL) 74 | { 75 | eH = head; 76 | eL = head; 77 | } 78 | else 79 | { 80 | eL->next = head; 81 | eL = eL->next; 82 | } 83 | 84 | } 85 | else 86 | { 87 | if (bH == NULL) 88 | { 89 | bH = head; 90 | bL = head; 91 | } 92 | else 93 | { 94 | bL->next = head; 95 | bL = bL->next; 96 | } 97 | } 98 | head = head->next; 99 | } 100 | if (sL) // 把前一段的末尾连到下一段的开头,但若前一段为空则不用考虑 101 | { 102 | sL->next = eH; // 若下一段为空则连到下下一段 103 | eL = eL==NULL ? bH:eL; 104 | } 105 | if (eL) 106 | { 107 | eL->next = bH; 108 | } 109 | 110 | if (bL) 111 | { 112 | bL->next = NULL; 113 | } 114 | else 115 | { 116 | if (eL) 117 | eL->next = NULL; 118 | else 119 | sL->next = NULL; 120 | } 121 | 122 | return sH==NULL ? eH==NULL?bH:eH : sH; 123 | } 124 | 125 | void print_list(list_node * head) 126 | { 127 | while (head != NULL) { 128 | printf("%d ", head->val); 129 | head = head->next; 130 | } 131 | } 132 | 133 | 134 | int main () 135 | { 136 | list_node * head = input_list(); 137 | head = list_partition(head, pivot); // 注意有返回值 138 | print_list(head); 139 | return 0; 140 | } -------------------------------------------------------------------------------- /CH2_LinkedList/8b_Partition.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 2019-10.30 3 | 链表--将单链表按某值划分成左边小。中间相等、右边大的形式 4 | 时间O(N),空间O(1) 5 | 输入: 6 | 5 3 7 | 9 0 4 5 1 8 | 9 | 输出 10 | 1 0 4 5 9 11 | ''' 12 | 13 | import sys 14 | import pdb 15 | 16 | class Node: 17 | def __init__(self, val): 18 | self.val = val 19 | self.next = NULL 20 | 21 | 22 | if __name__ == '__main__': 23 | Node node = NULL 24 | print(node.val) 25 | 26 | 27 | -------------------------------------------------------------------------------- /CH2_LinkedList/9a_Random_LinkedList.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-11.4 3 | 复制带有随机指针节点的链表 4 | 时间O(N),空间O(N) 5 | 6 | class Node { 7 | public: 8 | int val; 9 | Node* next; 10 | Node* random; 11 | Node() {} 12 | Node(int _val, Node* _next, Node* _random) { 13 | val = _val; 14 | next = _next; 15 | random = _random; 16 | } 17 | }; 18 | */ 19 | class Solution { 20 | public: 21 | Node* copyRandomList(Node* head) { 22 | Node* cur = head; 23 | map hash; 24 | while (cur) 25 | { 26 | hash[cur] = new Node(); 27 | hash[cur]->val = cur->val; 28 | cur = cur->next; 29 | } 30 | cur = head; 31 | while (cur) 32 | { 33 | hash[cur]->next = hash[cur->next]; // hash[]不能掉,否则会接到原链表上!! 34 | hash[cur]->random = hash[cur->random]; 35 | cur = cur->next; 36 | } 37 | return hash[head]; 38 | } 39 | }; -------------------------------------------------------------------------------- /CH2_LinkedList/9b_Random_LinkedList.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-11.4 3 | 复制带有随机指针节点的链表 4 | 时间O(N),空间O(1) 5 | 注意LeetCode有输入为空的Bug 6 | class Node { 7 | public: 8 | int val; 9 | Node* next; 10 | Node* random; 11 | 12 | Node() {} 13 | 14 | Node(int _val, Node* _next, Node* _random) { 15 | val = _val; 16 | next = _next; 17 | random = _random; 18 | } 19 | }; 20 | */ 21 | class Solution { 22 | public: 23 | Node* copyRandomList(Node* head) { 24 | if (head == NULL) 25 | return NULL; 26 | Node* cur = head; 27 | while (cur) 28 | { 29 | Node* node = new Node(cur->val); 30 | node->next = cur->next; 31 | cur->next = node; 32 | cur = cur->next->next; 33 | } 34 | 35 | cur = head; 36 | Node* cur2 = NULL; 37 | while (cur) // Random的修改 38 | { 39 | cur2 = cur->next; // 注意步骤不能反 40 | cur2->random = cur->random==NULL ? NULL : cur->random->next; 41 | cur = cur->next->next; 42 | } 43 | 44 | cur2 = head->next; 45 | // cur = NULL; 46 | Node* hhead = head; 47 | while (hhead->next) 48 | { 49 | cur = hhead->next; 50 | hhead->next = cur->next; // head->cur->... 51 | hhead = cur; 52 | // cur = cur->next; 53 | } 54 | return cur2; 55 | } 56 | }; -------------------------------------------------------------------------------- /CH2_LinkedList/ans.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberSpaceWang/Algorithm_Interview/f7c083bb6fb348bee5b08f38da648dd72ef81660/CH2_LinkedList/ans.txt -------------------------------------------------------------------------------- /CH2_LinkedList/in.txt: -------------------------------------------------------------------------------- 1 | 9 2 | 6 4 7 3 | 4 2 5 4 | 2 1 3 5 | 5 0 0 6 | 1 0 0 7 | 3 0 0 8 | 7 0 9 9 | 9 8 0 10 | 8 0 0 -------------------------------------------------------------------------------- /CH2_LinkedList/out.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberSpaceWang/Algorithm_Interview/f7c083bb6fb348bee5b08f38da648dd72ef81660/CH2_LinkedList/out.txt -------------------------------------------------------------------------------- /CH3_Binary_Tree/.idea/CH3_Binary_Tree.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CH3_Binary_Tree/.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /CH3_Binary_Tree/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /CH3_Binary_Tree/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CH3_Binary_Tree/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CH3_Binary_Tree/.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 11 | 12 | 13 | 14 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 1576397709494 32 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /CH3_Binary_Tree/1a_Traverse_Recursive.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-12.1 3 | 二叉树的遍历 4 | 输入: 5 | 3 1 6 | 1 2 3 7 | 2 0 0 8 | 3 0 0 9 | 输出: 10 | 1 2 3 11 | 2 1 3 12 | 2 3 1 13 | */ 14 | 15 | #include 16 | using namespace std; 17 | 18 | struct Node 19 | { 20 | int val; 21 | Node *left, *right; 22 | }; 23 | 24 | Node* Construct() // 构造二叉树 25 | { 26 | // 输入格式: 节点个数+头结点编号 27 | // 每行对应当前节点的编号、左右儿子, 0表示是空节点 28 | int n, root_ind; 29 | cin >> n >> root_ind; 30 | Node *node = new Node[n+1]; // 注意默认构造函数问题! 31 | int fa, lch, rch; 32 | for (int i = 1; i <= n; i++) 33 | { 34 | cin >> fa >> lch >> rch; 35 | node[fa].val = fa; 36 | node[fa].left = lch!=0 ? &node[lch] : NULL; // 是0则为NULL,否则指向lch的地址 37 | node[fa].right = rch!=0 ? &node[rch] : NULL; 38 | } 39 | return &node[root_ind]; // 返回指针 40 | } 41 | 42 | 43 | void PreOrder(Node* root) // 先序:中左右 44 | { 45 | if (root == NULL) 46 | return ; 47 | cout << root->val << " "; 48 | PreOrder(root->left); 49 | PreOrder(root->right); 50 | } 51 | 52 | void InOrder(Node* root) // 中序:左中右 53 | { 54 | if (root == NULL) 55 | return ; 56 | InOrder(root->left); 57 | cout << root->val << " "; 58 | InOrder(root->right); 59 | } 60 | 61 | void PosOrder(Node* root) // 后序:左右中 62 | { 63 | if (root == NULL) 64 | return ; 65 | PosOrder(root->left); 66 | PosOrder(root->right); 67 | cout << root->val << " "; 68 | } 69 | 70 | 71 | int main() 72 | { 73 | Node *root = Construct(); // 构建二叉树 74 | PreOrder(root); 75 | cout << endl; 76 | InOrder(root); 77 | cout << endl; 78 | PosOrder(root); 79 | return 0; 80 | } 81 | 82 | -------------------------------------------------------------------------------- /CH3_Binary_Tree/2_Print_Edge_Node.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-12.15 3 | 打印二叉树边界节点 4 | 输入: 5 | 太多 6 | 输出: 7 | 1 2 4 7 11 13 14 15 16 12 10 6 3 8 | 1 2 4 7 13 14 15 16 10 6 3 9 | */ 10 | 11 | #include 12 | #include 13 | using namespace std; 14 | 15 | struct Node 16 | { 17 | int val; 18 | Node *left, *right; 19 | }; 20 | 21 | Node* Construct() // 构造二叉树 22 | { 23 | int n, root_ind; 24 | cin >> n >> root_ind; 25 | Node *node = new Node[n+1]; // 注意默认构造函数问题! 26 | int fa, lch, rch; 27 | for (int i = 1; i <= n; i++) 28 | { 29 | cin >> fa >> lch >> rch; 30 | node[fa].val = fa; 31 | node[fa].left = lch!=0 ? &node[lch] : NULL; // 是0则为NULL,否则指向lch的地址 32 | node[fa].right = rch!=0 ? &node[rch] : NULL; 33 | } 34 | return &node[root_ind]; // 返回指针 35 | } 36 | 37 | 38 | const int maxn = 1000005; 39 | int edgemap[maxn][2]; 40 | int height = -1; // 树的高度 41 | 42 | // 标准一 43 | void setEdgeMap1(Node* node, int h, int edgemap[][2]) // 类似于先序遍历 44 | { 45 | if (node == NULL) 46 | { 47 | if (h > height) 48 | height = h; 49 | return ; 50 | } 51 | edgemap[h][0] = edgemap[h][0]==0? node->val : edgemap[h][0]; 52 | edgemap[h][1] = node->val; 53 | setEdgeMap1(node->left, h+1, edgemap); 54 | setEdgeMap1(node->right, h+1, edgemap); 55 | } 56 | 57 | // 标准二 58 | void setEdgeMap2Left(Node* node, int h, int edgemap[][2]) // 类似于先序遍历 59 | { 60 | if (!node->left && !node->right) 61 | return ; 62 | edgemap[h][0] = node->val; 63 | if (node->left) 64 | setEdgeMap2Left(node->left, h+1, edgemap); 65 | else 66 | setEdgeMap2Left(node->right, h+1, edgemap); 67 | } 68 | 69 | void setEdgeMap2Right(Node* node, int h, int edgemap[][2]) 70 | { 71 | if (!node->left && !node->right) 72 | return ; 73 | edgemap[h][1] = node->val; 74 | if (node->right) 75 | setEdgeMap2Right(node->right, h+1, edgemap); 76 | else 77 | setEdgeMap2Right(node->left, h+1, edgemap); 78 | } 79 | 80 | // 打印叶子节点(不包括最左/右) 81 | void printLeaf(Node* node, int h, int edgemap[][2]) 82 | { 83 | if (node == NULL) 84 | return ; 85 | if (!node->left && !node->right && edgemap[h][0] != node->val && edgemap[h][1] != node->val) 86 | cout << node->val << " "; 87 | printLeaf(node->left, h+1, edgemap); 88 | printLeaf(node->right, h+1, edgemap); 89 | } 90 | 91 | 92 | int main() 93 | { 94 | Node *root = Construct(); // 构建二叉树 95 | memset(edgemap, 0, sizeof(edgemap)); 96 | 97 | /* ----------------- 标准一 -------------------*/ 98 | setEdgeMap1(root, 0, edgemap); // 寻找边界点 99 | for (int i = 0; i < height; i++) // 打印左边界点 100 | cout << edgemap[i][0] << " "; 101 | printLeaf(root, 0, edgemap); // 打印叶子节点 102 | for (int i = height-1; i >= 0; i--) 103 | if (edgemap[i][0] != edgemap[i][1]) // 打印右边界点 104 | cout << edgemap[i][1] << " "; 105 | cout << endl; 106 | /* ----------------- 标准二 -------------------*/ 107 | memset(edgemap, 0, sizeof(edgemap)); 108 | setEdgeMap2Left(root, 0, edgemap); // 构建左右两边 109 | setEdgeMap2Right(root, 0, edgemap); 110 | for (int i = 0; i < height; i++) 111 | if (edgemap[i][0] != 0) 112 | cout << edgemap[i][0] << " "; 113 | printLeaf(root, 0, edgemap); 114 | for (int i = height-1; i >= 0; i--) 115 | if (edgemap[i][0] != edgemap[i][1] && edgemap[i][1] != 0) 116 | cout << edgemap[i][1] << " "; 117 | return 0; 118 | } 119 | -------------------------------------------------------------------------------- /CH3_Binary_Tree/3a_Sequence_Inverse.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2019-12.15 3 | 二叉树的序列化(先续与层序序列化) 4 | 输入: 5 | 2 1 6 | 1 2 0 7 | 2 0 0 8 | 输出: 9 | 1!2!#!#!#! 10 | 1!2!#!#!#! 11 | */ 12 | 13 | #include 14 | using namespace std; 15 | 16 | struct Node 17 | { 18 | int val; 19 | Node *left, *right; 20 | }; 21 | 22 | Node* Construct() // 构造二叉树 23 | { 24 | int n, root_ind; 25 | cin >> n >> root_ind; 26 | Node *node = new Node[n+1]; // 注意默认构造函数问题! 27 | int fa, lch, rch; 28 | for (int i = 1; i <= n; i++) 29 | { 30 | cin >> fa >> lch >> rch; 31 | node[fa].val = fa; 32 | node[fa].left = lch!=0 ? &node[lch] : NULL; // 是0则为NULL,否则指向lch的地址 33 | node[fa].right = rch!=0 ? &node[rch] : NULL; 34 | } 35 | return &node[root_ind]; // 返回指针 36 | } 37 | 38 | 39 | void PreOrder(Node* root) // 先序:中左右 40 | { 41 | if (root == NULL) 42 | return ; 43 | cout << root->val << " "; 44 | PreOrder(root->left); 45 | PreOrder(root->right); 46 | } 47 | 48 | 49 | int main() 50 | { 51 | Node *root = Construct(); // 构建二叉树 52 | PreOrder(root); 53 | cout << endl; 54 | 55 | return 0; 56 | } 57 | 58 | -------------------------------------------------------------------------------- /CH3_Binary_Tree/4_serialization.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | struct Node 6 | { 7 | int val; 8 | Node *left, *right; 9 | }; 10 | 11 | Node* Construct() // 构造二叉树 12 | { 13 | // 输入格式: 节点个数+头结点编号 14 | // 每行对应当前节点的编号、左右儿子, 0表示是空节点 15 | int n, root_ind; 16 | cin >> n >> root_ind; // 输入节点数和根节点 17 | Node *node = new Node[n+1]; // 注意默认构造函数问题! 18 | int fa, lch, rch; 19 | for (int i = 1; i <= n; i++) 20 | { 21 | cin >> fa >> lch >> rch; 22 | node[fa].val = fa; 23 | node[fa].left = lch!=0 ? &node[lch] : NULL; // 是0则为NULL,否则指向lch的地址 24 | node[fa].right = rch!=0 ? &node[rch] : NULL; 25 | } 26 | return &node[root_ind]; // 返回指针 27 | } 28 | 29 | void PreOrder(Node* root) // 先序:中左右 30 | { 31 | if (root == NULL) { 32 | cout << "#!"; 33 | return ; 34 | } 35 | cout << root->val << "!"; 36 | PreOrder(root->left); 37 | PreOrder(root->right); 38 | } 39 | 40 | void LevelOrder(Node* root) { 41 | queue q; 42 | q.push(root); 43 | while (!q.empty()) { 44 | Node* temp = q.front(); 45 | q.pop(); 46 | if (temp == NULL) // 确保后面的工作都不做 47 | cout << "#!"; 48 | else { 49 | cout << temp->val << "!"; 50 | q.push(temp->left); 51 | q.push(temp->right); 52 | } 53 | } 54 | } 55 | 56 | int main() 57 | { 58 | Node *root = Construct(); // 构建二叉树 59 | PreOrder(root); 60 | cout << endl; 61 | LevelOrder(root); 62 | return 0; 63 | } -------------------------------------------------------------------------------- /CH3_Binary_Tree/6_max_path_len.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2020-3.22 3 | 在二叉树中找到累加和为指定值的最长路径 4 | 输入: 5 | */ 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | struct Node 11 | { 12 | int val; 13 | Node *left, *right; 14 | }; 15 | 16 | Node* Construct() // 构造二叉树 17 | { 18 | // 输入格式: 节点个数+头结点编号 19 | // 每行对应当前节点的编号、左右儿子, 0表示是空节点 20 | int n, root_ind; 21 | cin >> n >> root_ind; // 输入节点数和根节点 22 | Node *node = new Node[n+1]; // 注意默认构造函数问题! 23 | int fa, lch, rch; 24 | for (int i = 1; i <= n; i++) 25 | { 26 | cin >> fa >> lch >> rch; 27 | node[fa].val = fa; 28 | node[fa].left = lch!=0 ? &node[lch] : NULL; // 是0则为NULL,否则指向lch的地址 29 | node[fa].right = rch!=0 ? &node[rch] : NULL; 30 | } 31 | return &node[root_ind]; // 返回指针 32 | } -------------------------------------------------------------------------------- /CH3_Binary_Tree/ans.txt: -------------------------------------------------------------------------------- 1 | 1 2 | 3 3 | 4 4 | -------------------------------------------------------------------------------- /CH3_Binary_Tree/in.txt: -------------------------------------------------------------------------------- 1 | 2 1 2 | 1 2 0 3 | 2 0 0 4 | -------------------------------------------------------------------------------- /CH3_Binary_Tree/out.txt: -------------------------------------------------------------------------------- 1 | 1 2 | 3 3 | 4 4 | -------------------------------------------------------------------------------- /CH8_Array_Matrix/10_max_subarray_len_pos_element.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2020-3.22 3 | 未排序正数数组中累加和为给定值的最长子数组长度 4 | 输入: 5 | 5 3 6 | 1 2 1 1 1 7 | 输出: 8 | 3 9 | */ 10 | 11 | #include 12 | using namespace std; 13 | 14 | const int maxn = 100005; 15 | int arr[maxn]; 16 | 17 | int main() 18 | { 19 | int N, k; 20 | cin >> N >> k; 21 | for (int i = 0; i < N; i++) { 22 | cin >> arr[i]; 23 | } 24 | int left=0, right=0; 25 | int sum = arr[0]; // 注意: 在循环中, 判断的是上一次循环中的结果!! 26 | int max_len = 0; 27 | 28 | while (right < N) { // 每次循环只移动left或right, 且只移动一个单位 29 | if (sum == k) { // 最特殊的情况 30 | if ((right - left + 1) > max_len) { 31 | max_len = right - left + 1; 32 | } 33 | sum -= arr[left]; 34 | left++; 35 | } 36 | else if (sum < k) { // 普遍情况 37 | right++; 38 | if (right == N) // 此句别写会有bug!! 因为下一句可能导致数组越界 39 | break; 40 | sum += arr[right]; 41 | } 42 | else { // 如果超过范围, 大了, 退回 43 | sum -= arr[left]; 44 | left++; 45 | } 46 | } 47 | 48 | cout << max_len << endl; 49 | return 0; 50 | } -------------------------------------------------------------------------------- /CH8_Array_Matrix/in.txt: -------------------------------------------------------------------------------- 1 | 5 3 2 | 1 2 1 1 1 -------------------------------------------------------------------------------- /Cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberSpaceWang/Algorithm_Interview/f7c083bb6fb348bee5b08f38da648dd72ef81660/Cover.jpg -------------------------------------------------------------------------------- /Debug/Debug.cbp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 42 | 43 | -------------------------------------------------------------------------------- /Debug/Debug.depend: -------------------------------------------------------------------------------- 1 | # depslib dependency file v1.0 2 | 1569488680 source:c:\users\wyf\code\algorithm\interview\ch1_stack_queue\debug\main.cpp 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Debug/Debug.layout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Debug/debug.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | int a = 0; 8 | for (int i = 0; i < 5; i++) 9 | { 10 | cout << a << endl; 11 | } 12 | return 0; 13 | } -------------------------------------------------------------------------------- /Debug/in.txt: -------------------------------------------------------------------------------- 1 | 5 2 | 1 2 3 4 5 3 | -------------------------------------------------------------------------------- /Debug/main.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberSpaceWang/Algorithm_Interview/f7c083bb6fb348bee5b08f38da648dd72ef81660/Debug/main.cpp -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 程序员代码面试指南:IT名企算法与数据结构题目最优解 2 | 3 | **Wang Yufei, 2019-9.24** 4 | 5 |    本项目用于复现**左程云老师**书籍《**程序员代码面试指南:IT名企算法与数据结构题目最优解**》(第二版)中算法代码。作者使用Java作为[书中代码](http://www.broadview.com.cn/book/4889)的实现方式,并采用面向对象方式进行封装(风格类似于LeetCode)。本人参照作者思路(可能会有些许变动),使用C++进行编程复现。编写的代码均可在[牛客网评测系统](https://www.nowcoder.com/ta/programmer-code-interview-guide)中成功通过测试。:arrow_down: 6 | 7 | **请原谅:由于本人能力有限,部分难题(主要为4星)无法复现!谢谢** 8 | 9 | ![Cover](./Cover.jpg) 10 | 11 | **做题流程**: 12 | 13 | 1. 看清题目、输入输出等; 14 | 2. 考察所有可能的情况,整理思路,将过程完整的模拟一遍,讨论细节; 15 | 3. 编写代码、注意细节实现。 16 | 17 | **测试说明**: 18 | 19 |   以**Linux**为例,使用`g++`编译源代码、`gdb`调试代码,并使用输入输出重定向解决测试数据问题!样例如下: 20 | 21 | ```shell 22 | $ g++ -g test.cpp -o test # -g表示开启调试模式, -o指示可执行文件名称:test 23 | $ ./test < in.txt # 重定向输入,将结果显示在命令行 24 | # 若需要调试 25 | $ gdb test 26 | ``` 27 | 28 | 若程序输出较长,需要与正确输出进行逐一比较(如第一章第4题),可以创建out.txt(保存程序输出)和ans.txt(保存正确输出),使用Linux管道(`|`)、分流技术(`tee`)以及比较命令`diff`进行对比: 29 | 30 | ```shell 31 | $ ./test < in.txt | tee out.txt # 运行test,结果显示在命令行并保存至out.txt 32 | $ diff out.txt ans.txt # 比较程序输出和正确的输出,若相同则返回空! 33 | ``` 34 | 35 | ## 常用数据结构的实现 36 | 37 |   本块列举书中所涉数据结构的实现。其中部分数据结构本人尝试使用C++或python手编实现(可能并不整洁高效,为demo版),也可直接调用C++ STL(标准模板库)实现,详见[STL官方文档](http://www.cplusplus.com/reference/stl/)。 38 | 39 | | 对应书中章节 | 数据结构 | STL官方文档 | 实现方式(demo版) | 40 | | :----------: | :------: | :----------------------------------------------------------: | :--------------------------------------------: | 41 | | 1 | 栈 | [stack](http://www.cplusplus.com/reference/stack/stack/) | [Python](ADT_py/Stack.py) | 42 | | 1 | 队列 | [queue](http://www.cplusplus.com/reference/queue/queue/) | [Python](ADT_py/Queue.py) | 43 | | 1 | 双端队列 | [deque](http://www.cplusplus.com/reference/deque/deque/) | [Python](ADT_py/Deque.py) | 44 | | 2 | 链表 | [list](http://www.cplusplus.com/reference/list/list/) | [C++](ADT_cpp/LinkList_demo.cpp) | 45 | | 3 | 二叉树 | 无 | [C++](ADT_cpp/Binary_Tree.cpp) | 46 | | 5 | 字符串 | [C++ String类](http://www.cplusplus.com/reference/string/string/) | 无 | 47 | | 9 | 计算几何 | 无 | [C++](ADT_cpp/Coputational_Geometry.cpp)(未完) | 48 | 49 | ## 第一章:栈与队列 50 | 51 | | 序号 | 题目 | 难度 | 完成时间 | 实现 | 标签 | 52 | | :--: | :----------------------------------------------------------: | :--: | :--------: | :----------------------------------------------------------: | :--------------: | 53 | | 1 | [设计getMin功能的栈](https://www.nowcoder.com/practice/05e57ce2cd8e4a1eae8c3b0a7e9886be?tpId=101&tqId=33073&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 1 | 2019-9.24 | [C++](CH1_Stack_Queue/1_getMin.cpp),[Python](CH1_Stack_Queue/1_getMin.py) | 栈设计 | 54 | | 2 | [使用两个栈模拟队列](https://www.nowcoder.com/practice/6bc058b32ee54a5fa18c62f29bae9863?tpId=101&tqId=33074&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 2 | 2019-9.24 | [C++](CH1_Stack_Queue/2_stack_queue.cpp) | 栈设计 | 55 | | 3 | [用递归函数和栈逆序一个栈](https://www.nowcoder.com/practice/1de82c89cc0e43e9aa6ee8243f4dbefd?tpId=101&tqId=33075&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 2 | 2019-9.26 | [C++](CH1_Stack_Queue/3_Inverse_Stack_by_Recursion.cpp) | 递归 | 56 | | 4 | [猫狗队列](https://www.nowcoder.com/practice/8a7e04cff6a54b7095b94261d78108f5?tpId=101&tqId=33168&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 1 | 2019-10.3 | [C++](CH1_Stack_Queue/4_Dog_Cat_Queue.cpp) | 大模拟 | 57 | | 5 | [用一个栈实现另一个栈的排序](https://www.nowcoder.com/practice/ff8cba64e7894c5582deafa54cca8ff2?tpId=101&tqId=33081&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 1 | 2019-9.28 | [C++](CH1_Stack_Queue/5_Sort_Stack.cpp) | 栈设计 | 58 | | 6 | [用栈来求解汉诺塔问题](https://www.nowcoder.com/practice/1a2f618b3433487295657b3414f4e7c4?tpId=101&tqId=33090&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 3 | 2019-10.8 | [C++](CH1_Stack_Queue/6a_Hanoi_Recursive.cpp) | 递归 | 59 | | 7 | [生成窗口最大值数组](https://www.nowcoder.com/practice/b316c7f9617744b98fa311ae29ac516c?tpId=101&tqId=33083&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 2 | 2019-10.6 | [C++](CH1_Stack_Queue/7_Max_Windows_Array.cpp) | 双端队列 | 60 | | 8a | [单调栈结构--基础](https://www.nowcoder.com/practice/e3d18ffab9c543da8704ede8da578b55?tpId=101&tqId=33169&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 2 | 2019-10.11 | [C++_v1_](CH1_Stack_Queue/8a1_Monotate_Stack.cpp)
[C++_v2_](CH1_Stack_Queue/8a2_Monotate_Stack.cpp) | 模拟
单调栈 | 61 | | 8b | [单调栈结构--进阶](https://www.nowcoder.com/practice/2a2c00e7a88a498693568cef63a4b7bb?tpId=101&tqId=33256&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 3 | 2019-10.13 | [C++](CH1_Stack_Queue/8b_Monotate_Stack.cpp) | 数据组织 | 62 | | 9 | [最大子矩阵](https://www.nowcoder.com/practice/ed610b2fea854791b7827e3111431056?tpId=101&tqId=33084&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 3 | 2019-10.15 | [C++](CH1_Stack_Queue/9_Max_SubMatrix.cpp) | 单调栈应用 | 63 | | 10 | [最大值减最小值<=num的子数组数量](https://www.nowcoder.com/practice/5fe02eb175974e18b9a546812a17428e?tpId=101&tqId=33086&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 3 | 2019-10.17 | [C++](CH1_Stack_Queue/10_Max_Min_Num.cpp) | 双端队列应用 | 64 | | 11a | [可见山峰对数--基础](https://www.nowcoder.com/practice/80d076bcea594b86ba55b913de4c069d?tpId=101&tqId=33170&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 2 | 2019-10.17 | [C++](CH1_Stack_Queue/11_Mountain_Num.cpp) | 数学思维 | 65 | | 11b | [可见山峰对数--进阶](https://www.nowcoder.com/practice/16d1047e9fa54cea8b5170b156d89e38?tpId=101&tqId=33173&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 4 | | | 单调栈应用 | 66 | 67 | > **注**:8b题本人C++代码**超时**:仅通过75%测试样例!未能找到原因。 68 | 69 | ## 第二章:链表 70 | 71 | | 序号 | 题目 | 难度 | 完成时间 | 实现 | 标签 | 72 | | :--: | :----------------------------------------------------------: | :--: | :-------------: | :----------------------------------------------------------: | :---------------------------: | 73 | | 1 | [打印两个有序链表的公共部分](https://www.nowcoder.com/practice/8943eea40dbb4185b187d80fd050fee9?tpId=101&tqId=33116&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 1 | 2019-10.17 | [C++](CH2_LinkedList/1_Overlap_List.cpp) | 链表遍历 | 74 | | 2 | [删除链表倒数第K个节点](https://www.nowcoder.com/practice/e5d90aac4c8b4628aa70d9b6597c0560?tpId=101&tqId=33117&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 1 | 2019-10.19 | [C++](CH2_LinkedList/2_Delete_Lastk.cpp) | 链表遍历 | 75 | | 3 | 删除链表中间节点 | 1 | 2019-10.19 | [C++](CH2_LinkedList/3_Delete_Medium.cpp) | 链表遍历 | 76 | | 4 | [反转单向和双向链表](https://www.nowcoder.com/practice/b66a251dec8847f386bbe6cd96b7e9c8?tpId=101&tqId=33175&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 1 | 2019-10.19 | [C++](CH2_LinkedList/4_Reverse_LinkedList.cpp) | 链表遍历 | 77 | | 5 | [反转部分单链表](https://www.nowcoder.com/practice/f11155006f154419b0bef6de8918aea2?tpId=101&tqId=33176&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 2 | 2019-10.21 | [C++](CH2_LinkedList/5_Reverse_SubLinkedList.cpp) | 链表遍历 | 78 | | 6a | [环形链表的约瑟夫问题--基础](https://www.nowcoder.com/practice/c3b34059faf546d3a7ee28f2b0154286?tpId=101&tqId=33177&tPage=1&rp=1&ru=%2Fta%2Fprogrammer-code-interview-guide&qru=%2Fta%2Fprogrammer-code-interview-guide%2Fquestion-ranking) | 1 | 2019-10.23 | [C++](CH2_LinkedList/6a_Joseph.cpp) | 循环链表 | 79 | | 6b | [环形链表的约瑟夫问题--进阶](https://www.nowcoder.com/practice/67741e15f1404e9fb26fd8192f02a870?tpId=101&tqId=33178&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 3 | 2019-10.25 | [C++](CH2_LinkedList/6b_Joseph.cpp) | 数学思维 | 80 | | 7a | [判断链表是否是回文结构--基础](https://www.nowcoder.com/practice/4b13dff86de64f84ac284e31067b86e2?tpId=101&tqId=33179&tPage=1&rp=1&ru=%2Fta%2Fprogrammer-code-interview-guide&qru=%2Fta%2Fprogrammer-code-interview-guide%2Fquestion-ranking) | 1 | 2019-10.25 | [C++](CH2_LinkedList/7a2_Palindrome.cpp) | 栈设计 | 81 | | 7b | [判断链表是否是回文结构--进阶](https://www.nowcoder.com/practice/cdef686631204f079b8f36fe99602fca?tpId=101&tqId=33180&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 2 | 2019-10.27 | [C++](CH2_LinkedList/7b_Palindrome.cpp) | 跳跃指针+链表重构 | 82 | | 8 | [将单链表按某值划为左边小,
中间相等,右边大形式](https://www.nowcoder.com/practice/04fcabc5d76e428c8100dbd855761778?tpId=101&tqId=33181&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 2 | 2019-10.27 | [C++](CH2_LinkedList/8a_Partition.cpp) | Partition | 83 | | 9 | [复制含随机指针节点的链表
(LeetCode 138)](https://leetcode-cn.com/problems/copy-list-with-random-pointer/) | 2 | 2019-11.4 | [C++_v1_](CH2_LinkedList/9a_Random_LinkedList.cpp)
[C++_v2_](CH2_LinkedList/9b_Random_LinkedList.cpp) | 链表遍历+哈希表
链表遍历 | 84 | | 10 | [两个单链表值相加后的链表](https://www.nowcoder.com/practice/2d4ae9ef94c8412ebe49118f8e1da2df?tpId=101&tqId=33182&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 1 | 2019-10.30 | [C++_v1_](CH2_LinkedList/10a_Add_2LinkedList.cpp)
[C++_v2_](CH2_LinkedList/10b_Add_2LinkedList.cpp) | 栈设计
链表遍历 | 85 | | 11 | 两个单链表相交的一系列问题 | | | | | 86 | | 12 | [将单链表的每K个节点之间逆序](https://www.nowcoder.com/practice/66285653d28b4ed6a15613477670e936?tpId=101&tqId=33187&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 2 | 2019-11.16 | [C++_v1_](CH2_LinkedList/12a_Reverse_KNode.cpp)
[C++_v2_](CH2_LinkedList/12b_Reverse_KNode.cpp) | 栈设计、链表遍历 | 87 | | 13 | [删除无序单链表中重复出现的节点](https://www.nowcoder.com/practice/fb3105d036344c6a8ecbef996e0b23a0?tpId=101&tqId=33205&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 1 | 2019-11.16 | [C++_v1_](CH2_LinkedList/13a_Delete_Repeat_node.cpp)
[C++_v2_](CH2_LinkedList/13b_Delete_Repeat_node.cpp) | 哈希表
选择排序 | 88 | | 14 | [删除单链表中指定值节点](https://www.nowcoder.com/practice/1a5fd679e31f4145a10d46bb8fd3d211?tpId=101&tqId=33206&tPage=1&rp=1&ru=%2Fta%2Fprogrammer-code-interview-guide&qru=%2Fta%2Fprogrammer-code-interview-guide%2Fquestion-ranking) | 1 | 2019-11.16 | [C++](CH2_LinkedList/14_Delete_Specify_node.cpp) | 链表遍历 | 89 | | 15 | [将二叉搜索树转换为双向链表](https://www.nowcoder.com/practice/2d3188a7e3ce4af2a9ebd5b89843fced?tpId=101&tqId=33224&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 2 | 2019-12.7
| [C++_v1_](CH2_LinkedList/15a_Tree_List.cpp)
? | 二叉树遍历 | 90 | | 16 | [单链表的选择排序](https://www.nowcoder.com/practice/78f83c3f12d2464591ebc5a73183db35?tpId=101&tqId=33207&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 1 | 2019-11.23 | [C++](CH2_LinkedList/16_Selection_Sort.cpp) | 链表遍历 | 91 | | 17 | [一种怪异的链表删除方式](https://www.nowcoder.com/practice/86896a89874d4676a3c8d712d9a1eef4?tpId=101&tqId=33225&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 1 | 2019-11.23 | [C++](CH2_LinkedList/17_Delete_tempnode.cpp) | 技巧 | 92 | | 18 | [向有序的环形链表中插入新节点](https://www.nowcoder.com/practice/8a2ed8d048f241fd92b478140bad18a1?tpId=101&tqId=33226&tPage=1&rp=1&ru=%2Fta%2Fprogrammer-code-interview-guide&qru=%2Fta%2Fprogrammer-code-interview-guide%2Fquestion-ranking) | 1 | 2019-11.23 | [C++](CH2_LinkedList/18_Circular_List_Insert.cpp) | 循环链表 | 93 | | 19 | [合并两个有序链表](https://www.nowcoder.com/practice/98a51a92836e4861be1803aaa9037440?tpId=101&tqId=33227&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 1 | 2019-11.30 | [C++](CH2_LinkedList/19_Merge_2List.cpp) | 链表合并 | 94 | | 20 | [按照左右半区重新组合单链表](https://www.nowcoder.com/practice/a7a348bdb4634e228cf7704c8a2a8bda?tpId=101&tqId=33228&tPage=1&rp=1&ru=%2Fta%2Fprogrammer-code-interview-guide&qru=%2Fta%2Fprogrammer-code-interview-guide%2Fquestion-ranking) | 1 | 2019-11.30 | [C++](CH2_LinkedList/20_Left_RightMerge.cpp) | 链表合并 | 95 | 96 | > **注**:13题C++v2版因算法时间复杂度高而无法在OJ上通过测试。 97 | 98 | **链表总结**: 99 | 100 | - **删除链表某一节点**:需要记录该节点的前驱节点;(题目:2,6a,13) 101 | - **反转链表片段**:需要记录其中每一节点的前驱和后继节点;(题目:4,5,7b) 102 | - **快速找到链表中间节点**:记录当前节点以及对应的跳跃节点。当前节点移动一步,跳跃节点移动两步。当跳跃节点到达末尾时,当前节点就是链表的中间节点;(题目:3,7a,7b) 103 | 104 | - **利用栈解决链表问题**:可以使用栈解决链表的部分问题,如逆序、对称性、递归问题等。(题目:7a,10a,12a) 105 | 106 | 107 | 108 | ## 第三章:二叉树 109 | 110 | | 序号 | 题目 | 难度 | 完成时间 | 实现 | 标签 | 111 | | :--: | :----------------------------------------------------------: | :--: | :--------: | :----------------------------------------------: | :------------------------------------------: | 112 | | 1 | [递归遍历二叉树](https://www.nowcoder.com/practice/566f7f9d68c24691aa5abd8abefa798c?tpId=101&tqId=33229&tPage=1&rp=1&ru=%2Fta%2Fprogrammer-code-interview-guide&qru=%2Fta%2Fprogrammer-code-interview-guide%2Fquestion-ranking) | 1 | 2019-12.1 | [C++](CH3_Binary_Tree/1a_Traverse_Recursive.cpp) | 二叉树遍历 | 113 | | 2 | [打印二叉树边界节点](https://www.nowcoder.com/practice/33b88978734c42b68699d0c7cef9b598?tpId=101&tqId=33230&tPage=1&rp=1&ru=%2Fta%2Fprogrammer-code-interview-guide&qru=%2Fta%2Fprogrammer-code-interview-guide%2Fquestion-ranking) | 2 | 2019-12.15 | [C++](CH3_Binary_Tree/2_Print_Edge_Node.cpp) | 二叉树遍历 | 114 | | 3 | 如何直观打印二叉树 | | | | | 115 | | 4 | [二叉树的序列化与反序列化](https://www.nowcoder.com/practice/d6425eab86fc402085f9fafc0db97cc2?tpId=101&tqId=33231&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 1 | 2019-12.15 | [C++](CH3_Binary_Tree/4_serialization.cpp) | 序列化--二叉树遍历
反序列化--二叉树生成 | 116 | | 5 | 遍历二叉树的神级方法 | | | | | 117 | | 6 | [二叉树中累和为指定值的最长路径长度](https://www.nowcoder.com/practice/2d35bc3364e3470381bc4eebd9178747?tpId=101&tqId=33233&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 2 | | | | 118 | | | | | | | | 119 | | | | | | | | 120 | | | | | | | | 121 | 122 | 123 | 124 | ## 第八章:数组与矩阵 125 | 126 | | 序号 | 题目 | 难度 | 完成时间 | 实现 | 标签 | 127 | | :--: | :----------------------------------------------------------: | :--: | :-------: | :----------------------------------------------------------: | :----: | 128 | | | | | | | | 129 | | 10 | [未排序整数数组累加和为给定值的最大子数组长度](https://www.nowcoder.com/practice/a4e34287fa1b41f9bd41f957efbd5dff?tpId=101&tqId=33076&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking) | 2 | 2020-3.22 | [C++](./CH8_Array_Matrix/10_max_subarray_len_pos_element.cpp) | 双指针 | 130 | | | | | | | | 131 | 132 | --------------------------------------------------------------------------------