[leetcode]第 11 天 双指针(简单)、第 12 天 双指针(简单)、第 13 天 双指针(简单)
18. 删除链表的节点
思路
class Solution {
public ListNode deleteNode(ListNode head, int val) {
if(head == null) return null;
if(head.val == val) return head.next;
ListNode cur = head;
while(cur.next != null && cur.next.val != val)
cur = cur.next;
if(cur.next != null) cur.next = cur.next.next;
return head;
}
}
22. 链表中倒数第k个节点
思路
看了大佬的解法,太妙了
指针former先向前走n - k步,然后former和latter一起向前走,等到former = null时返回latter指向的节点。
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
ListNode former = head, latter = head;
for(int i = 0; i < k; i++)
former = former.next;
while(former != null) {
former = former.next;
latter = latter.next;
}
return latter;
}
}
21. 调整数组顺序使奇数位于偶数前面
思路
可以引入伪头节点,将所有节点添加到伪头节点之后
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode dum = new ListNode(0), cur = dum;
while(l1 != null && l2 != null) {
if(l1.val < l2.val) {
cur.next = l1;
l1 = l1.next;
}
else {
cur.next = l2;
l2 = l2.next;
}
cur = cur.next;
}
cur.next = l1 != null ? l1 : l2;
return dum.next;
}
}
52. 两个链表的第一个公共节点
思路
当两个链表都不为空时才有可能相交,因此如果二者如果有一个为null,那么一定不相交。
使用两个指针 node1,node2 分别指向两个链表 headA,headB 的头结点,然后同时分别逐结点遍历,当 node1 到达链表 headA 的末尾时,重新定位到链表 headB 的头结点;当 node2 到达链表 headB 的末尾时,重新定位到链表 headA 的头结点。
class Solution {
ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA == null || headB == null) return null;
ListNode A = headA, B = headB;
while (A != B) {
A = A != null ? A.next : headB;
B = B != null ? B.next : headA;
}
return A;
}
}
25.调整数组顺序使奇数位于偶数前面
思路
双指针,一个从头遍历一个从尾遍历。
class Solution {
public int[] exchange(int[] nums) {
int i = 0, j = nums.length - 1;
while(i < j && j > 0){
int tmp1 = nums[i], tmp2 = nums[j];
if(nums[i] % 2 == 0) tmp1 = nums[i];
else i++;
if(nums[j] % 2 != 0) tmp2 = nums[j];
else j--;
if(tmp1 % 2 == 0 && tmp2 % 2 != 0){
nums[i] = tmp2;
nums[j] = tmp1;
}
}
return nums;
}
}
57. 和为s的两个数字
思路
双指针,思路和上题一样
class Solution {
public int[] twoSum(int[] nums, int target) {
int i = 0, j = nums.length - 1;
while(i < j){
int res = nums[i] + nums[j];
if(res < target) i++;
else if(res > target) j--;
else return new int[] { nums[i], nums[j] };
}
return new int[0];
}
}
58 - I. 翻转单词顺序
思路
这种倒转的题第一反应是栈
class Solution {
public String reverseWords(String s) {
if(s == null) return s;
Stack<String> res = new Stack<>();
int left = 0, right = 0;
while(right < s.length()){
if(s.charAt(left) == ' '){
left++;
right = left;
continue;
}
if(s.charAt(right) != ' '){
right++;
if(right != s.length()) continue;
}
res.push(s.substring(left, right));
res.push(" ");
left = right;
}
if(res.isEmpty()) return "";
res.pop();
StringBuilder sb = new StringBuilder();
while(!res.isEmpty()){
sb.append(res.pop());
}
return sb.toString();
}
}
但是看官方的解法可以用API!可恶啊,还是对字符串的API不太熟练。。。
class Solution {
public String reverseWords(String s) {
s = s.trim();
List<String> wordList = Arrays.asList(s.split("\\s+"));
Collections.reverse(wordList);
return String.join(" ", wordList);
}
}