剑指offer 链表

来源:互联网 发布:windows 8系统安装 编辑:程序博客网 时间:2024/04/30 02:14

单向链表

遍历

1.1 题目(面试题5):从尾到头打印链表

解法一:借助栈;

import java.util.ArrayList;  import java.util.Stack;  public class Solution {      public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {          ArrayList<Integer> array=new ArrayList<Integer>();          if(listNode==null)              return array;          Stack<Integer> stack=new Stack<Integer>();          ListNode temp=listNode;          while(temp!=null){              stack.push(temp.val);              temp=temp.next;          }          while(!stack.isEmpty()){              array.add(stack.pop());          }          return array;      }  }  

解法二:递归的实现;

import java.util.ArrayList;  import java.util.Stack;  public class Solution {      public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {          ArrayList<Integer> array=new ArrayList<Integer>();          if(listNode==null)              return array;          if(listNode.next!=null){              array.addAll(printListFromTailToHead(listNode.next));          }          array.add(listNode.val);          return array;      }  }  

解法三:改变链表的指针指向(得修改输入的数据);

1.2 题目(面试题13):在O(1)时间删除链表结点

解法一:从头到尾遍历查找,O(n)的时间复杂度;

解法二:把要删除结点的下一个结点(充分利用结点信息)复制到当前结点,然后删除下一结点,时间复杂度(O(n-1)*O(1)+O(n))/n(注意要考虑尾结点的情况);

1.3 题目(面试题57):删除链表中重复的结点

import java.util.ArrayList;  public class Solution {      public ListNode deleteDuplication(ListNode pHead)      {          if(pHead==null || pHead.next==null)              return pHead;          ListNode temp=pHead;          ListNode preNode=new ListNode(0);          preNode.next=pHead;          pHead=preNode;          boolean flag=false; //因为删除操作和非删除不一样,所以需要标记一下          while(temp!=null){                     while(temp.next!=null && temp.val==temp.next.val){ //这个循环是关键,直到找到                  temp=temp.next;                  flag=true;              }              if(flag){                  preNode.next=temp.next;                  temp=temp.next;                  flag=false;              }              else{                  preNode=preNode.next;                  temp=temp.next;              }          }                   return pHead.next;      }  }  

反转

2.1 题目(面试题16):反转链表

解法一:头插法,有助于理解java中的HashMap

public class Solution {      public ListNode ReverseList(ListNode head) {          if(head==null || head.next==null)              return head;          ListNode nHead=new ListNode(0);          while(head!=null){              ListNode temp=head;              head=head.next;  ②              temp.next=nHead.next;              nHead.next=temp;                      }          return nHead.next;      }  }  
解法二:递归法

public class Solution {      public ListNode ReverseList(ListNode head) {          if(head==null || head.next==null)                return head;            ListNode nHead=ReverseList(head.next);          head.next.next=head;          head.next=null;          return nHead;        }  }  

插入
3.1 题目(面试题17):合并两个有序的链表

public class Solution {      public ListNode Merge(ListNode list1,ListNode list2) {          if(list1==null)              return list2;          else if(list2==null)              return list1;                         ListNode mergeHead=null;          if(list1.val>=list2.val){              mergeHead=new ListNode(list2.val);              mergeHead.next=Merge(list1,list2.next);          }else{              temp=new ListNode(list1.val);              temp.next=Merge(list1.next,list2);          }          return mergeHead;      }  }  

查找

4.1 题目(面试题37):两个链表的第一个公共结点

解法一:暴力搜索法;

解法二:见从尾到头遍历链表的辅助栈法;

解法三:快慢指针;

4.2 题目(面试题15):链表中的倒数第K个结点

解法一:遍历两次链表的解法,或者见从尾到头打印链表;

public class Solution {      public ListNode FindKthToTail(ListNode head,int k) {          if(head==null)              return null;          int count=0;          ListNode node=head;          while(node!=null){              count++;              node=node.next;          }          if(k>count)              return null;                    node=head;          int num=0;          while(node!=null){              num++;              if(num==(count-k+1)){                  break;              }              node=node.next;          }          return node;            }  }  

解法二:遍历一次的解法,即快慢指针的解法;

public class Solution {      public ListNode FindKthToTail(ListNode head,int k) {          if(head==null || k==0)              return null;          ListNode n1=head;          ListNode n2=head;          int count=0;          while(n1!=null){                         if(count>=k){                  n2=n2.next;              }              count++;              n1=n1.next;          }          if(count<k)              return null;          return n2;      }  }  

循环链表

5.1 题目(面试题56):链表中环的入口结点

解法一:先判断是不是有环,再计算环中结点的个数,再利用快慢指针找到环的入口结点,一个题当成三道题。

5.2 题目(面试题45):圆圈中最后剩下的数字,即约瑟夫环问题

解法一:借助循环链表;

解法二:数学规律;

5.3 循环缓存

复杂链表

6.1 题目(面试题26):复杂链表的复制

6.2 题目(面试题27):二叉搜索树与双向链表

0 0
原创粉丝点击