100352. 交換後字典序最小的字串
給你一個僅由數字組成的字串 s
,在最多交換一次 相鄰 且具有相同 奇偶性 的數字後,返回可以得到的字典序最小的字串。
如果兩個數字都是奇數或都是偶數,則它們具有相同的奇偶性。例如,5 和 9、2 和 4 奇偶性相同,而 6 和 9 奇偶性不同。
思路
從左到右掃一遍就行,交換的越早越好,因為字典序是從左往右看的
import java.util.Arrays; class Solution { public String getSmallestString(String s) { char[] charArray = s.toCharArray(); for (int i = 0; i < charArray.length - 1; i++) { int now = charArray[i] - '0', nxt = charArray[i + 1] - '0'; if (now % 2 == nxt % 2 && now > nxt) { char tmp = charArray[i]; charArray[i] = charArray[i + 1]; charArray[i + 1] = tmp; break; } } return new String(charArray); } }
100368. 從連結串列中移除在陣列中存在的節點
給你一個整數陣列 nums
和一個連結串列的頭節點 head
。從連結串列中移除所有存在於 nums
中的節點後,返回修改後的連結串列的頭節點。
思路
將nums轉成一個set,就能在O(1)的時間內判斷當前節點值在不在nums裡,然後掃一遍維護指標就行
當然還有一種方法是記錄那些沒在nums裡的節點值,重新做一個連結串列出來返回
import java.util.HashSet; import java.util.Set; class Solution { public ListNode modifiedList(int[] nums, ListNode head) { if (head == null) return null; Set<Integer> set = new HashSet<>(); for (int num : nums) { set.add(num); } ListNode newHead = head; while (newHead != null && set.contains(newHead.val)) newHead = newHead.next; if (newHead == null) return null; ListNode pre = newHead; while (pre.next != null) { ListNode now = pre.next; if (set.contains(now.val)) { pre.next = findNewNextNode(set, now); if (pre.next != null) pre = pre.next; continue; } pre = now; } return newHead; } private ListNode findNewNextNode(Set<Integer> set, ListNode now) { ListNode ans = now; while (set.contains(ans.val)) { ans = ans.next; if (ans == null) break; } return ans; } }
100361. 切蛋糕的最小總開銷 I
有一個 m x n
大小的矩形蛋糕,需要切成 1 x 1
的小塊。
給你整數 m
,n
和兩個陣列:
horizontalCut
的大小為m - 1
,其中horizontalCut[i]
表示沿著水平線i
切蛋糕的開銷。verticalCut
的大小為n - 1
,其中verticalCut[j]
表示沿著垂直線j
切蛋糕的開銷。
一次操作中,你可以選擇任意不是 1 x 1
大小的矩形蛋糕並執行以下操作之一:
- 沿著水平線
i
切開蛋糕,開銷為horizontalCut[i]
。 - 沿著垂直線
j
切開蛋糕,開銷為verticalCut[j]
。
每次操作後,這塊蛋糕都被切成兩個獨立的小蛋糕。
每次操作的開銷都為最開始對應切割線的開銷,並且不會改變。
請你返回將蛋糕全部切成 1 x 1
的蛋糕塊的 最小 總開銷。
思路
當你橫著切一刀時,豎著切時都要加一刀,豎著切同理,所以我們想每次切大的花費的邊,這樣就不會重複切多次。把橫邊和豎邊降序排序,維護兩個多切係數,每次選擇橫邊和豎邊較大的那邊來切,同時維護多切係數,橫的切一刀,豎邊的多切係數就要+1,反之同理
import java.util.Arrays; class Solution { public static int minimumCost(int m, int n, int[] horizontalCut, int[] verticalCut) { int cos = 0; int horizonNum = 1, verticalNum = 1; reverseOrderQuickSort(horizontalCut, 0, horizontalCut.length - 1); reverseOrderQuickSort(verticalCut, 0, verticalCut.length - 1); int i = 0, j = 0; while (i < horizontalCut.length || j < verticalCut.length) { if (i == horizontalCut.length) { cos += verticalCut[j] * verticalNum; j++; continue; } if (j == verticalCut.length) { cos += horizontalCut[i] * horizonNum; i++; continue; } if (horizontalCut[i] > verticalCut[j]) { cos += horizontalCut[i] * horizonNum; verticalNum++; i++; } else { cos += verticalCut[j] * verticalNum; horizonNum++; j++; } } return cos; } private static void reverseOrderQuickSort(int[] num, int left, int right) { if (left < right) { int i = left, j = right, n = num[left]; while (i < j) { while (i < j && num[j] <= n) j--; if (i < j) num[i++] = num[j]; while (i < j && num[i] > n) i++; if (i < j) num[j--] = num[i]; } num[i] = n; reverseOrderQuickSort(num, left, i - 1); reverseOrderQuickSort(num, i + 1, right); } } }
100367. 切蛋糕的最小總開銷 II
題意和剛剛一樣,在剛剛的基礎上增大n和m的資料量
思路
和第三題是一樣的,我的解法tle了,時間複雜度應該是一樣的,問題應該是手寫的快排沒有jdk的速度快,用jdk的api就能AC
import java.util.Arrays; class Solution { public long minimumCost(int m, int n, int[] horizontalCut, int[] verticalCut) { long cos = 0; int horizonNum = 1, verticalNum = 1; Arrays.sort(horizontalCut); Arrays.sort(verticalCut); int i = horizontalCut.length - 1, j = verticalCut.length - 1; while (i >= 0 || j >= 0) { if (j < 0 || i >= 0 && horizontalCut[i] > verticalCut[j]) { cos += (long) horizontalCut[i] * horizonNum; verticalNum++; i--; } else { cos += (long) verticalCut[j] * verticalNum; horizonNum++; j--; } } return cos; } }