关于单链表,比较特殊,在面试中,要时刻注意时间复杂度和额外空间复杂度的问题
所以在笔试中,额外空间的应用无所谓,能做到即可,可以使用数组作为额外空间来使用
而在面试中要注意把额外空间复杂度降到最小,所以用克隆的方式来代替额外空间
这样子可以用不多的几个变量来确定关系,而位置的关系是通过克隆的位置关系来去确定的,这样的好处是让复杂度变低的同时还达到很好的效果
基数排序:分别按照个十百为先分别排序,然后再往上排序,对于每一位都是已经排好序,虽然不用进行比较,但是花费的空间和时间 比较多
在排完序之后还保持着排序前的基本序列,在班级中按照成绩排,相同的排序按照学号前后
在小样本的时候采用一种排序方式,大样本的时候采用另一种,让整体复杂度减小
无序的,但有序表的key是有序的
增删改查的复杂度都是常数,但是这个常数可能比较大
unordermap,unordertree
也可以申请栈,将每个数遍历后都放进栈里面去,然后依次弹出,比较
可以采用快慢指针的方式,但是将头结点的下一位做慢指针,可以解决奇数和偶数问题
设置一个哈希表,将每个数的next和rand都放进哈希表里,第一次遍历老链表就是放进哈希表,第二次是根据哈希表里的next和rand,设置新链表的next和rand
直接插入克隆结点在当前结点后面,这样的话就不用在哈希表里设置next了,然后在遍历的时候设置一下边界,一对对遍历,存入rand即可,克隆节点的rand就是原本节点rand的克隆节点
可以申请哈希表额外空间,记录每个遍历后的结点,第一次重复访问到的节点就就是环的开头
快慢指针:一开始都在head,慢指针一次走一步,快指针一次走两步,会在环里相遇,相遇后,快指针回到head,快慢指针同时走,都走一步,最终会在环的开始节点相遇
判断两条链表是否在同一地址,即最后节点是否相同,因为当两条单链表有相交时,相交部分一定是相同的,next指针是不会断的。
判断最后节点相同时即可判断出他们相交
让长链表先走x 步,x为二者差值,然后二者同时走,一定会在相交节点相遇
cur1 = n>0 ? head1 : head2//谁长,谁的头是head1
cur2 = cur1 == head1 ? head2 : head1 //谁短,谁的头是cur2
重定位长短
如果是相同环,则把终止节点设置为俩链表入环节点,其余按照无环链表操作,如果不同环,从loop 1开始,如果遇得到loop2,则是不同入环节点,返回谁都可以,但如果没有,则不相交
思路:多个指针,有限几个变量,采用merge方法,拆分出左右两组链表,然后进行合并,大化小
class Solution {
public:
ListNode *Merge2(ListNode *phead1, ListNode *phead2){
if(phead1 == NULL) return phead2;
if(phead2 == NULL) return phead1;
ListNode *head = new ListNode(0);
ListNode *cur = head;
while(phead1 && phead2){
if(phead1->val > phead2->val){
cur->next = phead2;
phead2 = phead2->next;
}
else{
cur->next = phead1;
phead1 = phead1->next;
}
cur = cur->next;
}
if(phead1) cur->next = phead1;
else cur->next = phead2;
return head->next;
}
ListNode *pideMerge(vector &lists, int left, int right){
if(left > right) return NULL;
else if (left == right) return lists[left];
int mid = (left + right) / 2;
return Merge2(pideMerge(lists, left, mid), pideMerge(lists, mid+1, right));
}
ListNode *mergeKLists(vector &lists) {
return pideMerge(lists, 0, lists.size() - 1);
}
};
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead) {
if(pHead == NULL ) return NULL;
ListNode *slow = pHead;
ListNode *fast = pHead;
while(fast != NULL && fast->next != NULL){
slow = slow->next;
fast = fast->next->next;
if(slow == fast)
break;
}
if(fast == NULL || fast->next == NULL)
return NULL;
fast = pHead;
while(fast != slow){
fast = fast->next;
slow = slow->next;
}
return slow;
}
};
class Solution {
public:
ListNode* FindKthToTail(ListNode* pHead, int k) {
// write code here
while(pHead == NULL) return NULL;
ListNode *fast = pHead;
ListNode *slow = pHead;
for(int i=0; inext;
}
while(fast != NULL ){
slow = slow->next;
fast = fast->next;
}
return slow;
}
};
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
//添加表
ListNode* res = new ListNode(-1);
res->next = head;
//当前节点
ListNode* cur = head;
//前序节点
ListNode* pre = res;
ListNode* fast = head;
//快指针先行n步
while (n--)
fast = fast->next;
while (fast != NULL) {
fast = fast->next;
pre = cur;
cur = cur->next;
}
//删除该位置的节点
pre->next = cur->next;
//返回去掉头
return res->next;
}
};
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
ListNode l1 = pHead1, l2 = pHead2;
while(l1 != l2){
l1 = (l1==null)?pHead2:l1.next;
l2 = (l2==null)?pHead1:l2.next;
}
return l1;
}
链表相加
class Solution {
public:
ListNode *reverselist(ListNode *phead){
if(phead == NULL) return phead;
ListNode *cur = phead;
ListNode *pre = NULL;
while(cur != NULL){
ListNode *temp = cur->next;
cur->next = pre;
pre = cur;
cur = temp;
}
return pre;
}
ListNode* addInList(ListNode* head1, ListNode* head2) {
// write code here
if(head1 == NULL) return head2;
if(head2 == NULL) return head1;
head1 = reverselist(head1);
head2 = reverselist(head2);
ListNode *res = new ListNode(-1);
ListNode *head = res;
int carry = 0;
while(head1 != NULL || head2 != NULL || carry !=0){
int val1 = head1 == NULL ? 0:head1->val;
int val2 = head2 == NULL ? 0 : head2->val;
int temp = val1 + val2 + carry;
carry = temp/10;
temp %= 10;
head->next = new ListNode(temp);
head = head->next;
if(head1 != NULL){
head1 = head1->next;
}
if(head2 != NULL){
head2 = head2->next;
}
}
return reverselist(res->next);
}
};
public class Solution {
public ListNode addInList (ListNode head1, ListNode head2) {
// write code here
if(head1 == null)
return head2;
if(head2 == null){
return head1;
}
// 使用两个辅助栈,利用栈先进后出,相当于反转了链表
Stack stack1 = new Stack<>();
Stack stack2 = new Stack<>();
ListNode p1=head1;
ListNode p2=head2;
// 将两个链表的结点入栈
while(p1!=null){
stack1.push(p1);
p1=p1.next;
}
while(p2!=null){
stack2.push(p2);
p2=p2.next;
}
// 进位
int tmp = 0;
// 创建新的链表头节点
ListNode head = new ListNode(-1);
ListNode nHead = head.next;
while(!stack1.isEmpty()||!stack2.isEmpty()){
// val用来累加此时的数值(加数+加数+上一位的进位=当前总的数值)
int val = tmp;
// 栈1不为空的时候,弹出结点并累加值
if (!stack1.isEmpty()) {
val += stack1.pop().val;
}
// 栈2不为空的时候,弹出结点并累加值
if (!stack2.isEmpty()) {
val += stack2.pop().val;
}
// 求出进位
tmp = val/10;
// 进位后剩下的数值即为当前节点的数值
ListNode node = new ListNode(val%10);
// 将结点插在头部
node.next = nHead;
nHead = node;
}
if(tmp > 0){
// 头插
ListNode node = new ListNode(tmp);
node.next = nHead;
nHead = node;
}
return nHead;
}
}
单链表的排序
class Solution {
public:
ListNode* sortInList(ListNode* head) {
vector nums;
ListNode* p = head;
//遍历链表,将节点值加入数组
while(p != NULL){
nums.push_back(p->val);
p = p->next;
}
p = head;
//对数组元素排序
sort(nums.begin(), nums.end());
//遍历数组
for(int i = 0; i < nums.size(); i++){
//将数组元素依次加入链表
p->val = nums[i];
p = p->next;
}
return head;
}
};
class Solution {
public:
ListNode *mergelist(ListNode *phead1, ListNode *phead2){
if(phead1 == NULL) return phead2;
if(phead2 == NULL ) return phead1;
ListNode *head = new ListNode(0);
ListNode *cur = head;
while(phead1 && phead2){
if(phead1->val >phead2->val){
cur->next = phead2;
phead2 = phead2->next;
}else{
cur->next = phead1;
phead1 = phead1->next;
}
cur = cur->next;
}
if(phead1) cur->next = phead1;
else cur->next = phead2;
return head->next;
}
ListNode* sortInList(ListNode* head) {
// write code here
if(head == NULL || head->next == NULL) return head;
ListNode *left = head;
ListNode *mid = head->next;
ListNode *right = head->next->next;
while(right != NULL && right->next != NULL){
left = left->next;
mid = mid->next;
right = right->next->next;
}
//左边指针指向左段的左右一个节点,从这里断开
left->next = NULL;
//分成两段排序,合并排好序的两段
return mergelist(sortInList(head), sortInList(mid));
}
};
判断链表是否为回文结构
class Solution {
public:
bool isPail(ListNode* head) {
vector nums;
//将链表元素取出一次放入数组
while(head != NULL){
nums.push_back(head->val);
head = head->next;
}
//双指针指向首尾
int left = 0;
int right = nums.size() - 1;
//分别从首尾遍历,代表正序和逆序
while(left <= right){
//如果不一致就是不为回文
if(nums[left] != nums[right])
return false;
left++;
right--;
}
return true;
}
};
class Solution {
public:
ListNode *reverse(ListNode *head){
ListNode *pre = NULL;
while(head != NULL){
ListNode *next = head->next;
head->next = pre;
pre = head;
head = next;
}
return pre;
}
bool isPail(ListNode* head) {
// write code here
ListNode *slow = head->next;
ListNode *fast = head;
while(fast->next != NULL && fast->next->next != NULL){
slow = slow->next;
fast = fast->next->next;
}
fast = head;
slow = reverse(slow);
while(slow != NULL){
if(fast->val != slow->val) return false;
slow = slow->next;
fast = fast->next;
}
return true;
}
};
链表的奇偶重排
class Solution {
public:
ListNode* oddEvenList(ListNode* head) {
// write code here
if(head == NULL) return NULL;
ListNode *even = head->next;
ListNode *odd = head;
ListNode *evenodd = even;
while(even != NULL && even->next != NULL){
odd->next = even->next;
odd = odd->next;
even->next = odd->next;
even = even->next;
}
odd->next = evenodd;
return head;
}
};
删除有序链表中重复的所有元素
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
// write code here
if(head == NULL) return NULL;
ListNode *res = new ListNode(0);
res->next = head;
ListNode *cur = res;
while(cur->next != NULL && cur->next->next != NULL) {
if(cur->next->val == cur->next->next->val){
int temp = cur->next->val;
while(cur->next != NULL && cur->next->val == temp){
cur->next = cur->next->next;
}
}else cur = cur->next;
}
return res->next;
}
};
页面更新:2024-03-07
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号