目录
一、反转链表
leetcode
双指针法:时间复杂度O(n),空间复杂度O(1)
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
//申请节点,pre和 cur,pre指向null
ListNode pre = null;
ListNode cur = head;
ListNode tmp = null;
while(cur!=null) {
//记录当前节点的下一个节点
tmp = cur.next;
//然后将当前节点指向pre
cur.next = pre;
//pre和cur节点都前进一位
pre = cur;
cur = tmp;
}
return pre;
}
}
二、从尾到头打印链表(offer6)
输入:head = [1,3,2] 输出:[2,3,1] 数组返回
利用递归
: 先走至链表末端,回溯时依次将节点值加入列表 ,这样就可以实现链表值的倒序输出。
O(N)O(N)
class Solution {
ArrayList<Integer> list = new ArrayList<>();
public int[] reversePrint(ListNode head) {
recur(head);
int [] res = new int[list.size()];
for(int i = 0 ;i<res.length ; i++)
res[i]=list.get(i);
return res;
}
void recur (ListNode head){
if(head==null) return ;
recur(head.next); //这里
list.add(head.val);
}
}
方法二:辅助栈
//链表特点: 只能从前至后访问每个节点。
//链表特点: 只能从前至后访问每个节点。
class Solution {
public int[] reversePrint(ListNode head) {
LinkedList<Integer> stack = new LinkedList<Integer>();
while(head != null) {
stack.addLast(head.val);
head = head.next;
}
int[] res = new int[stack.size()];
for(int i = 0; i < res.length; i++)
res[i] = stack.removeLast();//出栈
return res;
}
}
三、合并两个有序链表(21)
递归实现
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
终止条件
:当 l1 为空或 l2 为空时结束
返回值
:每一层调用都返回排序好的链表头
本级递归内容:如果 l1 的 val 值更小,则将 l1.next 与排序好的链表头相接,l2 同理
O(m+n),mm 为 l1的长度,nn 为 l2 的长度
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if(l1==null) return l2;
if(l2==null) return l1;//谁为空,返回第二个
if(l1.val<l2.val){ //l1小,都加到l1,后边一个递归比较
l1.next = mergeTwoLists(l1.next,l2);
return l1;
}else {
l2.next = mergeTwoLists(l1,l2.next);
return l2;
}
}
}
四、删除链表中的重复数字(83)
给定一个排序链表,删除所有重复元素,使得每个元素出现一次。
输入
: 1->1->2
输出
: 1->2
去重
:当 cur.val 和==cur.next.val ,则将 cur 的下一个指针指向下一个的下一个,这样就能达到去重复的效果
如果不相等则 cur 移动到下一个位置继续循环
时间复杂度:O(n)
public ListNode deleteDuplicates(ListNode head) {
ListNode cur = head;//指向头
while(cur!=null && cur.next!=null){ //循环结束条件,都存在
if(cur.val==cur.next.val){ //相等要去重
cur.next = cur.next.next; //指向下一个的下一个位置
}else{
cur=cur.next; //不相等,就下一个继续循环
}
}
return head;
}}
五、移除链表中重复数字(offer)
HashSet哈希表
编写代码,移除未排序链表中的重复节点。保留最开始出现的节点。 输入:[1, 2, 3, 3, 2, 1] 输出:[1, 2, 3]
public ListNode removeDuplicateNodes(ListNode head) {
if(head==null) return head;
HashSet<Integer> set = new HashSet<>();
set.add(head.val); //头节点的值肯定要加的
ListNode pos = head;//指针后移,head是返回用的
while(pos.next!=null){// 枚举前驱节点
ListNode cur = pos.next; // 当前待删除节点
if(set.add(cur.val)){ //true or false
pos=pos.next;
}else{
pos.next= pos.next.next;}
}pos.next = null;
return head;
}
六、删除链表的节点(18offer)
定位节点: 遍历链表,直到
head.val == val
时跳出,即可定位目标节点。
修改引用: 设节点 cur 的前驱节点为 pre ,后继节点为 cur.next ;则执行 pre.next =cur.next ,即可实现删除 cur 节点
class Solution {
public ListNode deleteNode(ListNode head, int val) {
if(head==null) return null; //一般写一下
if(head.val==val) return head.next; //考虑情况
ListNode cur = head ;//指向头,好处是最后返回head
while(cur.next!=null && cur.next.val!= val){
cur=cur.next;
} //不满足,说明定位节点
if(cur.next!=null)
cur.next = cur.next.next;
return head;
}
}
第七题:判断链表有环
public class Solution {
public boolean hasCycle(ListNode head) {
if(head==null||head.next==null) return false;
ListNode slow = head;
ListNode fast = head;
while(fast.next !=null && fast!=null){
slow = slow.next;
fast = fast.next.next;
if(slow == fast)
return true;
}
return false;
}
}