虚拟头节点 移除链表元素
leetcode203https://leetcode.com/problems/r…
1 2 3 4 5 6 7 8 9 struct ListNode { int val; ListNode *next; ListNode () : val (0 ), next (nullptr ) {} ListNode (int x) : val (x), next (nullptr ) {} ListNode (int x, ListNode *next) : val (x), next (next) {} };
若直接使用原始链表,删除头节点的操作与其他节点不同
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 while (head != NULL && head->val == val) { ListNode* tmp = head; head = head->next; delete tmp; } ListNode* cur = head; while (cur != NULL && cur->next!= NULL ) { if (cur->next->val == val) { ListNode* tmp = cur->next; cur->next = cur->next->next; delete tmp; } else cur = cur->next; }
使用虚拟头节点:
1 2 3 4 ListNode* dummyHead=new ListNode (-1 ); dummyHead->next=head
代码为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution {public : ListNode* removeElements (ListNode* head, int val) { ListNode *dummyHead=new ListNode (-1 ); dummyHead->next=head; auto vi=dummyHead; while (vi->next!=nullptr ) { if (vi->next->val==val){ auto tmp=vi->next; vi->next=tmp->next; delete tmp; } else vi=vi->next; } head=dummyHead->next; delete dummyHead; return head; } };
反转链表 反转链表I https://leetcodereverse-linked-list/
双指针法 pre与cur指针
1 2 3 4 5 6 7 8 9 10 11 12 13 class Solution {public : ListNode* reverseList (ListNode* head) { ListNode *pre=nullptr ,*cur=head; while (cur){ ListNode* temp=cur->next; cur->next=pre; pre=cur; cur=temp; } return pre; } };
递归法 1 2 3 4 5 6 7 8 9 10 11 12 13 class Solution {public : ListNode* reverseList (ListNode* head) { return rev (head,NULL ); } private : ListNode* rev (ListNode* cur,ListNode* pre) { if (cur==nullptr ) return pre; auto temp=cur->next; cur->next=pre; return rev (temp,cur); } };
反转链表II leetcode.com/problems…
截断 截断待反转的区域,将它反转再重新插入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 class Solution {private : void rev (ListNode *head) { ListNode *cur=head,*pre=nullptr ; while (cur){ auto tmp=cur->next; cur->next=pre; pre=cur; cur=tmp; } } public : ListNode* reverseBetween (ListNode* head, int left, int right) { if (right==left) return head; ListNode *dummyHead=new ListNode (-1 ); dummyHead->next=head; ListNode *pre=dummyHead,*rtnode,*ltnode,*nex; for (int i=0 ;i<left-1 ;++i){ pre=pre->next; } ltnode=pre->next; rtnode=ltnode; for (int i=0 ;i<right-left;++i){ rtnode=rtnode->next; } nex=rtnode->next; pre->next=NULL ; rtnode->next=NULL ; rev (ltnode); pre->next=rtnode; ltnode->next=nex; return dummyHead->next; } };
头插法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution {public : ListNode* reverseBetween (ListNode* head, int left, int right) { if (left==right) return head; ListNode* dummyNode=new ListNode (-1 ); dummyNode->next=head; ListNode *cur,*Next,*pre=dummyNode; for (int i=0 ;i<left-1 ;++i){ pre=pre->next; } cur=pre->next; for (int i=0 ;i<right-left;++i){ Next=cur->next; cur->next=Next->next; Next->next=pre->next; pre->next=Next; } return dummyNode->next; } };
环 leetcode环形链表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class Solution {public : ListNode *detectCycle (ListNode *head) { ListNode *fast=head,*slow=head; while (fast&&fast->next) { fast=fast->next->next; slow=slow->next; if (fast==slow){ ListNode *ind1=head,*ind2=fast; while (ind1!=ind2){ ind1=ind1->next; ind2=ind2->next; } return ind1; } } return nullptr ; } };
单向链表排序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 class Solution { public : ListNode* sortList (ListNode* head) { ListNode* dummyHead=new ListNode; dummyHead->next=head; int len=0 ; ListNode* p=head; while (p) { ++len; p=p->next; } for (int i=1 ;i<len;i<<=1 ) { ListNode* cur=dummyHead->next; ListNode* tail=dummyHead; while (cur) { auto left=cur; auto right=cut (left,i); cur=cut (right,i); tail->next=merge (left,right); while (tail->next) tail=tail->next; } } auto ret=dummyHead->next; delete dummyHead; return ret; } private : ListNode* cut (ListNode* head,int n) { ListNode* cur=head; while (--n && cur) cur=cur->next; if (!cur) return nullptr ; ListNode* ret=cur->next; cur->next=nullptr ; return ret; } ListNode* merge (ListNode* left,ListNode* right) { ListNode* dummyHead=new ListNode; ListNode* p=dummyHead; while (left && right) { if (left->val<right->val) { p->next=left; p=left; left=left->next; } else { p->next=right; p=right; right=right->next; } } p->next= left ? left : right; auto ret=dummyHead->next; delete dummyHead; return ret; } };
计算PI 利用反三角函数幂级展开式进行计算
经计算,取n = 2000可以保证前550位的精度
模拟大数运算 乘法 从尾至头做乘法,处理进位。若有溢出,可在链表头部添加节点,也可以不加。
1、添加节点后,增加的是整数位,小数点后位数不变,由于乘发结束后要除以一个更大的数
(即2*i-1 > i - 1),整数位均变为0,执行加法时,从两链表尾部开始遍历,到短链表头处终止即可,前面整数部分的零无需参与加法运算。
2、不添加节点,整数位会大于10,同理,做除法后整数位必定为零,因此只需处理第2位及以后的进位。
加法与除法 分别倒序顺序遍历。
除法运算还有构建链表的作用,在计算过程中向后补位。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 #include <iostream> using namespace std;struct LinkedNode { int val; LinkedNode* next; LinkedNode* pre; LinkedNode* tail; LinkedNode () : val (0 ), next (nullptr ), pre (nullptr ), tail (this ) { } LinkedNode (int val) : val (val), next (nullptr ), pre (nullptr ), tail (this ) { } }; using Lptr = LinkedNode*;class Caculation { public : void operator +(Caculation& cal); void operator *(int val); void operator /(int val); void print (int n) ; void init () ; void initRet () ; Caculation () { init (); } Caculation (int ) { initRet (); } Lptr getP () {return p;} private : Lptr p; }; const int Max = 550 ;int main () { int n; scanf ("%d" , &n); Caculation result (1 ) , head ; for (int i = 2 ; i <= 2000 ; ++i) { head * (i - 1 ); head / ((i << 1 ) - 1 ); result + head; } result * 2 ; result.print (n); return 0 ; } void Caculation::init () { p = new LinkedNode (0 ); auto q = new LinkedNode (1 ); q->pre = p; p->next = q; p->tail = q; } void Caculation::initRet () { p = new LinkedNode (0 ); auto L = p; for (int i = 0 ; i <= Max; ++i) { auto cur = new LinkedNode (0 ); cur->pre = L; L->next = cur; L = cur; } p->next->val = 1 ; p->tail = L; } void Caculation::print (int n) { auto cur = p->next; printf ("%d." , cur->val); cur = cur->next; for (int i = 0 ; i < n; ++i) { printf ("%d" ,cur->val); cur = cur->next; } } void Caculation::operator +(Caculation& cal){ auto p2 = cal.getP (); Lptr t1 = this ->p->tail, t2 = p2->tail; while (t1 != this ->p && t2 != p2) { t1->val += t2->val; t1->pre->val += t1->val / 10 ; t1->val %= 10 ; t1 = t1->pre; t2 = t2->pre; } } void Caculation::operator /(int val){ int carry (0 ) ; int len (0 ) ; auto cur = p->next; Lptr pre; while (cur) { cur->val += carry * 10 ; carry = cur->val % val; cur->val /= val; pre = cur; cur = cur->next; ++len; } cur = pre; while (carry && len <= Max) { auto newNode = new LinkedNode (0 ); newNode->val = carry * 10 ; newNode->pre = cur; carry = newNode->val % val; cur->next = newNode; newNode->val /= val; cur->next = newNode; cur = newNode; ++len; } p->tail = cur; } void Caculation::operator *(int val){ Lptr cur = p->tail; while (cur != p) { cur->val *= val; cur = cur->pre; } cur = p->tail; while (cur != p->next) { cur->pre->val += cur->val / 10 ; cur->val %= 10 ; cur = cur->pre; } while (cur->val >= 10 ) { auto newNode = new LinkedNode (0 ); newNode->val = cur->val / 10 ; cur->val %= 10 ; newNode->pre = p; newNode->next = cur; p->next = newNode; cur->pre = newNode; cur = newNode; } }