栈
每周一句:万物自有节奏,忙有价值,闲有滋味。
5.3.反转链表
-
题目:给定单链表的头节点
head,请反转链表,并返回反转后的链表的头节点。 -
示例:
示例 1: 输入:head = [1,2,3,4,5] 输出:[5,4,3,2,1] 示例 2: 输入:head = [1,2] 输出:[2,1] 示例 3: 输入:head = [] 输出:[] -
思路:
- 双指针定义两个指针,遍历进行交换
- 递归
-
代码实现
if(head == null || head.next == null){ return head; } ListNode cur = head; ListNode pre = null; while(cur != null){ ListNode temp = cur.next; cur.next = pre; pre = cur; cur = temp; } return pre; } class Solution { public ListNode reverseList(ListNode head) { if(head == null || head.next == null){ return head; } return reverse(head,null); } public ListNode reverse(ListNode cur, ListNode pre){ if(cur == null){ return pre; } ListNode temp = cur.next; cur.next = pre; return reverse(temp,cur); } }
5.4.两两交换链表
-
题目:给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
-
示例:
示例 1: 输入:head = [1,2,3,4] 输出:[2,1,4,3] 示例 2: 输入:head = [] 输出:[] 示例 3: 输入:head = [1] 输出:[1] -
思路:
- 定义虚拟头节点
- 创建指针指向虚拟头节点,在交换,然后移动cur节点到要交换链表的前一个节点再次进行交换
-
代码:
class Solution { public ListNode swapPairs(ListNode head) { if(head == null || head.next == null){ return head; } ListNode dummHead = new ListNode(-1); dummHead.next = head; ListNode cur = dummHead; while(cur.next != null && cur.next.next != null){ ListNode temp = cur.next.next.next; ListNode temp1 = cur.next; cur.next = cur.next.next; cur.next.next = temp1; temp1.next = temp; cur = cur.next.next; } return dummHead.next; } }
5.5.删除链表的倒数第 N 个结点
-
题目:给你一个链表,删除链表的倒数第
n个结点,并且返回链表的头结点。 -
示例:
示例 1: 输入:head = [1,2,3,4,5], n = 2 输出:[1,2,3,5] 示例 2: 输入:head = [1], n = 1 输出:[] 示例 3: 输入:head = [1,2], n = 1 输出:[1] -
思路:
- 创建虚拟头节点来操作
- 创建快慢指针,让快指针先走n步,快慢指针再一起走
- 直到快指针到了链表尾部,让慢指针所在的节点只想下下个节点
-
代码
class Solution { public ListNode removeNthFromEnd(ListNode head, int n) { ListNode dummyHead = new ListNode(-1); dummyHead.next = head; ListNode fast = dummyHead; ListNode slow = dummyHead; while(n+1 != 0){ fast = fast.next; n--; } while(fast != null){ fast = fast.next; slow = slow.next; } slow.next = slow.next.next; return dummyHead.next; } }
哈希表
6.1.有效的字母异位词
-
题目:
-
给定两个字符串
*s*和*t*,编写一个函数来判断*t*是否是*s*的字母异位词。注意: 若
*s*和*t*中每个字符出现的次数都相同,则称*s*和*t*互为字母异位词。 -
示例
示例 1: 输入: s = "anagram", t = "nagaram" 输出: true 示例 2: 输入: s = "rat", t = "car" 输出: false -
思路
- 利用数组来求解,因为只有26个字母所以先创建一个数组大小为26的数组
- 又因为字母的相减是数值,我们只需要让每个字符去减去字母a就可以得到字母对应为位置,因为字母的ASCII是递增的,所以用所有的字母减去a就会得到对应的位置
- 找到位置后++,然后再操作另一个但是是减减
- 只要数组没有!=0就为异位词
-
代码
class Solution { public boolean isAnagram(String s, String t) { if(s.length() != t.length()){ return false; } int[] arr = new int[26]; for(int i = 0; i < s.length(); i++){ arr[s.charAt(i) - 'a']++; } for(int i = 0; i < t.length(); i++){ arr[t.charAt(i) - 'a']--; } for(int i : arr){ if(i != 0){ return false; } } return true; } }
6.2.两个数组的交集
-
题目:给定两个数组
nums1和nums2,返回 它们的 交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 -
示例:
示例 1: 输入:nums1 = [1,2,2,1], nums2 = [2,2] 输出:[2] 示例 2: 输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4] 输出:[9,4] 解释:[4,9] 也是可通过的 -
思路
- 先将第一个数组存到hash里面
- 创建个新的判断hash中是否包含第二个数组的值,包含直接放入新的hash里面
-
代码
class Solution { public int[] intersection(int[] nums1, int[] nums2) { HashMap<Integer, Integer> map = new HashMap<>(); Arrays.stream(nums1).forEach(n ->map.put(n,n)); Set<Integer> objects = new HashSet<Integer>(){ }; for (int i : nums2) { if(map.containsKey(i)){ objects.add(map.get(i)); } } return objects.stream().mapToInt(x -> x).toArray(); } }