算法通关2.数组和链表
2019-08-21 本文已影响0人
YangDxg
数组
数组:内存里连续的一段存储区域
取:取元素时间复杂度为O(1)
插入:需要挪动插入位置后面的元素,时间复杂度为O(n)
删除:同插入,后面的元素需要向前挪动,时间复杂度为O(n)
链表
单向链表:用一个指针链向下一个元素
双向链表:用俩个指针链向上一个元素和下一个元素
增加删除只需要更改指针指向即可,时间复杂度O(1)
查找时间复杂度是O(n)
练习
-
leetcode206反转链表
输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL
思路:定义俩个变量,记录当前节点和上一个节点,采用俩数交换的方式进行反转
class Solution { public ListNode reverseList(ListNode head) { ListNode cur = head; ListNode prev = null; ListNode tempNext = null; while (cur != null) { tempNext = cur.next; cur.next = prev; prev = cur; cur = tempNext; } return prev; } }
-
leetcode24两两交互链表中的节点
给定 1->2->3->4, 你应该返回 2->1->4->3.
递归解乏
public static ListNode swapPairs(ListNode head) { if (head == null || head.next == null) { return head; } ListNode next = head.next; head.next = swapPairs(next.next); next.next = head; return next; }
非递归解法
public static ListNode swapPairs2(ListNode head) { ListNode prev = new ListNode(0); prev.next = head; ListNode temp = prev; while (temp.next != null && temp.next.next != null) { ListNode start = temp.next; ListNode end = temp.next.next; temp.next = end; start.next = end.next; end.next = start; temp = start; } return prev.next; }
-
环形链表
给定一个链表,判断链表中是否有环。
img输入:head = [3,2,0,-4], pos = 1 输出:true 解释:链表中有一个环,其尾部连接到第二个节点。
思路:如何判断一个链表是否有环
-
硬做(在0.5s内判断会不会走到null,性能很差)
-
把走过的节点放到set中,每到新节点判断set中有没有进行判重,时间复杂度O(n)
public boolean hasCycle(ListNode head) { Set<ListNode> nodes = new HashSet<>(); while (head != null) { if (nodes.contains(head)) { return true; } nodes.add(head); head = head.next; } return false; }
-
龟兔赛跑式(快慢指针),快指针每次走俩步,慢指针每次走一步,快慢相遇说明有环
public boolean hasCycle(ListNode head) { if (head == null || head.next == null) { return false; } ListNode fast = head; ListNode slow = head; while (fast.next != null && fast.next.next != null) { slow = slow.next; fast = fast.next.next; if (slow == fast) { return true; } } return false; }