1、week3
1.1、有效的括号
20 - 有效的括号
| public boolean isValid(String s) { |
| Deque<Character> stack = new ArrayDeque<>(); |
| char[] chars = s.toCharArray(); |
| for (char c : chars) { |
| if (c == '(' || c == '[' || c == '{') stack.addLast(c); |
| else { |
| if (stack.isEmpty()) return false; |
| char top = stack.removeLast(); |
| if (c == ')' && top != '(') return false; |
| if (c == ']' && top != '[') return false; |
| if (c == '}' && top != '{') return false; |
| } |
| } |
| return stack.isEmpty(); |
| } |
1.2、用队列实现栈
225 - 用队列实现栈
| public class MyStack { |
| |
| private final Queue<Integer> q; |
| |
| public MyStack() { |
| q = new LinkedList<>(); |
| } |
| |
| |
| public void push(int x) { |
| q.add(x); |
| for (int i = 0; i < q.size() - 1; i++) q.add(q.remove()); |
| } |
| |
| public int pop() { |
| return q.remove(); |
| } |
| |
| public int top() { |
| return q.peek(); |
| } |
| |
| public boolean empty() { |
| return q.isEmpty(); |
| } |
| } |
1.3、用栈实现队列
232 - 用栈实现队列
| public class MyQueue { |
| |
| private Stack<Integer> stack1; |
| private Stack<Integer> stack2; |
| private int front; |
| |
| public MyQueue() { |
| stack1 = new Stack<>(); |
| stack2 = new Stack<>(); |
| } |
| |
| public void push(int x) { |
| if (stack1.isEmpty()) front = x; |
| stack1.push(x); |
| } |
| |
| |
| public int pop() { |
| if (!stack2.isEmpty()) return stack2.pop(); |
| while (stack1.size() != 1) stack2.push(stack1.pop()); |
| return stack1.pop(); |
| } |
| |
| public int peek() { |
| if (!stack2.isEmpty()) return stack2.peek(); |
| return front; |
| } |
| |
| public boolean empty() { |
| return stack1.isEmpty() && stack2.isEmpty(); |
| } |
| } |
2、week4
2.1、反转链表
206 - 反转链表
| |
| |
| |
| |
| |
| public static ListNode reverseList(ListNode head) { |
| ListNode prev = null; |
| ListNode cur = head; |
| ListNode next; |
| while (cur != null) { |
| next = cur.next; |
| cur.next = prev; |
| prev = cur; |
| cur = next; |
| } |
| return prev; |
| } |
| |
| |
| |
| |
| public static ListNode reverseList(ListNode head) { |
| if (head == null || head.next == null) return head; |
| |
| ListNode newHead = reverseList(head.next); |
| head.next.next = head; |
| head.next = null; |
| |
| return newHead; |
| } |
2.2、移除链表元素
203 - 移除链表元素
| |
| |
| |
| public static ListNode removeElements(ListNode head, int val) { |
| ListNode dummyHead = new ListNode(-1, head); |
| |
| ListNode prev = dummyHead; |
| while (prev.next != null) { |
| if (prev.next.val == val) prev.next = prev.next.next; |
| else prev = prev.next; |
| } |
| |
| return dummyHead.next; |
| } |
| |
| |
| |
| |
| public static ListNode removeElements(ListNode head, int val) { |
| if (head == null) return null; |
| head.next = removeElements(head.next, val); |
| return head.val == val ? head.next : head; |
| } |
3、week5 逆序数对
剑指 Offer 51 - 数组中的逆序对

| |
| |
| |
| public static int reversePairs(int[] nums) { |
| return sort(nums); |
| } |
| |
| private static int sort(int[] arr) { |
| int[] temp = new int[arr.length]; |
| return process(arr, 0, arr.length - 1, temp); |
| } |
| |
| private static int process(int[] arr, int l, int r, int[] temp) { |
| |
| if (r - l <= 15) return insertionSort(arr, l, r); |
| |
| int mid = l + (r - l) / 2; |
| int left = process(arr, l, mid, temp); |
| int right = process(arr, mid + 1, r, temp); |
| |
| if (arr[mid] > arr[mid + 1]) return left + right + merge(arr, l, mid, r, temp); |
| return left + right; |
| } |
| |
| private static int merge(int[] arr, int l, int mid, int r, int[] temp) { |
| int res = 0; |
| System.arraycopy(arr, l, temp, l, r - l + 1); |
| |
| int p1 = l; |
| int p2 = mid + 1; |
| int i = l; |
| |
| while (p1 <= mid && p2 <= r) { |
| if (temp[p1] > temp[p2]) { |
| |
| |
| |
| |
| res += mid - p1 + 1; |
| arr[i++] = temp[p2++]; |
| } else { |
| arr[i++] = temp[p1++]; |
| } |
| } |
| while (p1 <= mid) arr[i++] = temp[p1++]; |
| while (p2 <= r) arr[i++] = temp[p2++]; |
| return res; |
| } |
| |
| private static int insertionSort(int[] arr, int l, int r) { |
| int res = 0; |
| for (int i = l + 1; i <= r; i++) { |
| int k = arr[i]; |
| int j; |
| for (j = i; j - 1 >= l && arr[j - 1] > k; j--) { |
| arr[j] = arr[j - 1]; |
| } |
| arr[j] = k; |
| res += i - j; |
| } |
| return res; |
| } |
4、week6

4.1、Select K 问题
215 - 数组中的第 K 个最大元素
| |
| |
| |
| |
| public static int findKthLargest(int[] arr, int k) { |
| return selectK(arr, 0, arr.length - 1, arr.length - k, new Random()); |
| } |
| |
| private static int selectK(int[] arr, int l, int r, int k, Random random) { |
| int p = partition(arr, l, r, random); |
| |
| if (p == k) return arr[p]; |
| |
| if (p < k) return selectK(arr, p + 1, r, k, random); |
| return selectK(arr, l, p - 1, k, random); |
| } |
| |
| |
| |
| |
| private static int partition(int[] arr, int l, int r, Random random) { |
| int p = random.nextInt(r - l + 1) + l; |
| swap(arr, l, p); |
| |
| int v = arr[l]; |
| int p1 = l + 1; |
| int p2 = r; |
| |
| while (true) { |
| while (p1 <= p2 && arr[p1] < v) p1++; |
| while (p1 <= p2 && arr[p2] > v) p2--; |
| |
| if (p1 >= p2) break; |
| |
| swap(arr, p1++, p2--); |
| } |
| |
| swap(arr, l, p2); |
| return p2; |
| } |
| |
| private static void swap(int[] arr, int a, int b) { |
| int k = arr[a]; |
| arr[a] = arr[b]; |
| arr[b] = k; |
| } |
4.2、Top K 问题
面试题 17.14. 最小 K 个数
| |
| |
| |
| |
| public static int[] smallestK(int[] arr, int k) { |
| if (k == 0) return new int[0]; |
| return selectK(arr, 0, arr.length - 1, k - 1, new Random()); |
| } |
| |
| private static int[] selectK(int[] arr, int l, int r, int k, Random random) { |
| int p = partition(arr, l, r, random); |
| |
| if (p == k) return Arrays.copyOf(arr, k + 1); |
| |
| if (p < k) return selectK(arr, p + 1, r, k, random); |
| return selectK(arr, l, p - 1, k, random); |
| } |
| |
| |
| |
| |
| private static int partition(int[] arr, int l, int r, Random random) { |
| int p = random.nextInt(r - l + 1) + l; |
| swap(arr, l, p); |
| |
| int v = arr[l]; |
| int p1 = l + 1; |
| int p2 = r; |
| |
| while (true) { |
| while (p1 <= p2 && arr[p1] < v) p1++; |
| while (p1 <= p2 && arr[p2] > v) p2--; |
| |
| if (p1 >= p2) break; |
| |
| swap(arr, p1++, p2--); |
| } |
| |
| swap(arr, l, p2); |
| return p2; |
| } |
| |
| private static void swap(int[] arr, int a, int b) { |
| int k = arr[a]; |
| arr[a] = arr[b]; |
| arr[b] = k; |
| } |
5、week7
5.1、爱吃香蕉的珂珂
875 - 爱吃香蕉的珂珂
| public static int minEatingSpeed(int[] piles, int h) { |
| int speedL = 1; |
| int speedR = Arrays.stream(piles).max().getAsInt(); |
| int speedMid; |
| |
| |
| |
| |
| while (speedL < speedR) { |
| speedMid = speedL + (speedR - speedL) / 2; |
| int time = getEatingTime(piles, speedMid); |
| if (time <= h) speedR = speedMid; |
| else speedL = speedMid + 1; |
| } |
| |
| return speedR; |
| } |
| |
| private static int getEatingTime(int[] piles, int speed) { |
| int times = 0; |
| for (int pile : piles) { |
| times += pile / speed + (pile % speed == 0 ? 0 : 1); |
| } |
| return times; |
| } |
5.2、在 D 天内送达包裹的能力
1011 - 在 D 天内送达包裹的能力
| public static int shipWithinDays(int[] weights, int days) { |
| int capacityL = Arrays.stream(weights).max().getAsInt(); |
| int capacityR = Arrays.stream(weights).sum(); |
| int capacityMid; |
| |
| |
| |
| |
| while (capacityL < capacityR) { |
| capacityMid = capacityL + (capacityR - capacityL) / 2; |
| int times = getShipTime(weights, capacityMid); |
| if (times <= days) capacityR = capacityMid; |
| else capacityL = capacityMid + 1; |
| } |
| |
| return capacityR; |
| } |
| |
| private static int getShipTime(int[] weights, int maxCapacity) { |
| int times = 0; |
| int hasCapacity = 0; |
| for (int weight : weights) { |
| if (hasCapacity + weight <= maxCapacity) hasCapacity += weight; |
| else { |
| times++; |
| hasCapacity = weight; |
| } |
| } |
| return times + 1; |
| } |
6、week8
6.1、两个数组的交集
349 - 两个数组的交集
| public static int[] intersection(int[] nums1, int[] nums2) { |
| TreeSet<Integer> set = new TreeSet<>(); |
| for (int num : nums1) set.add(num); |
| |
| ArrayList<Integer> list = new ArrayList<>(); |
| for (int num : nums2) { |
| if (set.contains(num)) { |
| list.add(num); |
| set.remove(num); |
| } |
| } |
| |
| int[] res = new int[list.size()]; |
| for (int i = 0; i < list.size(); i++) res[i] = list.get(i); |
| return res; |
| } |
6.2、两个数组的交集 II
350 - 两个数组的交集 II
| public static int[] intersect(int[] nums1, int[] nums2) { |
| TreeMap<Integer, Integer> map = new TreeMap<>(); |
| for (int num : nums1) { |
| if (!map.containsKey(num)) map.put(num, 1); |
| else map.put(num, map.get(num) + 1); |
| } |
| |
| ArrayList<Integer> list = new ArrayList<>(); |
| for (int num : nums2) { |
| if (map.containsKey(num)) { |
| list.add(num); |
| map.put(num, map.get(num) - 1); |
| if (map.get(num) == 0) map.remove(num); |
| } |
| } |
| |
| int[] res = new int[list.size()]; |
| for (int i = 0; i < list.size(); i++) res[i] = list.get(i); |
| return res; |
| } |
6.3、唯一摩尔斯密码词
804 - 唯一摩尔斯密码词
| public static int uniqueMorseRepresentations(String[] words) { |
| String[] codes = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--.."}; |
| Set<String> set = new TreeSet<>(); |
| |
| StringBuilder sb = new StringBuilder(); |
| for (String word : words) { |
| for (int i = 0; i < word.length(); i++) { |
| sb.append(codes[word.charAt(i) - 'a']); |
| } |
| set.add(sb.toString()); |
| sb.delete(0, sb.length()); |
| } |
| |
| return set.size(); |
| } |
7、week9
7.1、Select K 问题
215 - 数组中的第 K 个最大元素
| |
| public static int findKthLargest(int[] arr, int k) { |
| PriorityQueue<Integer> pq = new PriorityQueue<>(); |
| for (int i = 0; i < k; i++) pq.add(arr[i]); |
| for (int i = k; i < arr.length; i++) { |
| if (arr[i] > pq.peek()) { |
| pq.remove(); |
| pq.add(arr[i]); |
| } |
| } |
| |
| return pq.peek(); |
| } |
| |
| public static int findKthLargest(int[] arr, int k) { |
| int[] minHeap = Arrays.copyOf(arr, k); |
| int last = k - 1; |
| for (int i = (last - 1) / 2; i >= 0; i--) siftDown(minHeap, i); |
| |
| for (int i = k; i < arr.length; i++) { |
| if (arr[i] > minHeap[0]) { |
| minHeap[0] = arr[i]; |
| siftDown(minHeap, 0); |
| } |
| } |
| |
| return minHeap[0]; |
| } |
| |
| private static void siftDown(int[] arr, int index) { |
| int last = arr.length - 1; |
| while (index * 2 + 1 <= last) { |
| int smaller = index * 2 + 1; |
| if (smaller + 1 <= last && arr[smaller + 1] < arr[smaller]) smaller++; |
| |
| if (arr[index] <= arr[smaller]) break; |
| swap(arr, index, smaller); |
| index = smaller; |
| } |
| } |
| |
| private static void swap(int[] arr, int a, int b) { |
| int k = arr[a]; |
| arr[a] = arr[b]; |
| arr[b] = k; |
| } |
7.2、Top K 问题
面试题 17.14. 最小 K 个数
| |
| public static int[] smallestK(int[] arr, int k) { |
| if (k == 0) return new int[0]; |
| |
| PriorityQueue<Integer> pq = new PriorityQueue<>(Collections.reverseOrder()); |
| for (int i = 0; i < k; i++) pq.add(arr[i]); |
| |
| for (int i = k; i < arr.length; i++) { |
| if (arr[i] < pq.peek()) { |
| pq.remove(); |
| pq.add(arr[i]); |
| } |
| } |
| |
| int[] res = new int[k]; |
| for (int i = 0; i < k; i++) res[i] = pq.remove(); |
| return res; |
| } |
| |
| public static int[] smallestK(int[] arr, int k) { |
| if (k == 0) return new int[0]; |
| |
| int[] maxHeap = Arrays.copyOf(arr, k); |
| int last = k - 1; |
| for (int i = (last - 1) / 2; i >= 0; i--) siftDown(maxHeap, i); |
| |
| for (int i = k; i < arr.length; i++) { |
| if (arr[i] < maxHeap[0]) { |
| maxHeap[0] = arr[i]; |
| siftDown(maxHeap, 0); |
| } |
| } |
| |
| return maxHeap; |
| } |
| |
| private static void siftDown(int[] arr, int index) { |
| int last = arr.length - 1; |
| while (index * 2 + 1 <= last) { |
| int bigger = index * 2 + 1; |
| if (bigger + 1 <= last && arr[bigger + 1] > arr[bigger]) bigger++; |
| |
| if (arr[index] >= arr[bigger]) break; |
| swap(arr, index, bigger); |
| index = bigger; |
| } |
| } |
| |
| private static void swap(int[] arr, int a, int b) { |
| int k = arr[a]; |
| arr[a] = arr[b]; |
| arr[b] = k; |
| } |
8、week11
8.1、区域和检索 I
303 - 区域和检索 - 数组不可变
| |
| public class NumArray { |
| |
| private final int[] sum; |
| |
| public NumArray(int[] nums) { |
| sum = new int[nums.length]; |
| sum[0] = nums[0]; |
| for (int i = 1; i < nums.length; i++) sum[i] = sum[i - 1] + nums[i]; |
| } |
| |
| public int sumRange(int left, int right) { |
| if (left == 0) return sum[right]; |
| return sum[right] - sum[left - 1]; |
| } |
| } |
8.2、区域和检索 II
307 - 区域和检索 - 数组可修改
| |
| public class NumArray { |
| |
| private final int[] arr; |
| private final int[] sum; |
| |
| public NumArray(int[] nums) { |
| arr = Arrays.copyOf(nums, nums.length); |
| sum = new int[nums.length]; |
| |
| sum[0] = arr[0]; |
| for (int i = 1; i < arr.length; i++) sum[i] = sum[i - 1] + arr[i]; |
| } |
| |
| |
| |
| |
| public void update(int index, int val) { |
| int diff = val - arr[index]; |
| arr[index] = val; |
| for (int i = index; i < sum.length; i++) sum[i] += diff; |
| } |
| |
| public int sumRange(int left, int right) { |
| if (left == 0) return sum[right]; |
| return sum[right] - sum[left - 1]; |
| } |
| } |
| |
| public class NumArray { |
| |
| private final int[] data; |
| private final int[] tree; |
| |
| public NumArray(int[] nums) { |
| data = Arrays.copyOf(nums, nums.length); |
| tree = new int[nums.length * 4]; |
| buildSegmentTree(0, 0, data.length - 1); |
| } |
| |
| private void buildSegmentTree(int treeIndex, int l, int r) { |
| if (l == r) { |
| tree[treeIndex] = data[l]; |
| return; |
| } |
| |
| int mid = l + (r - l) / 2; |
| int leftTreeIndex = leftChild(treeIndex); |
| int rightTreeIndex = rightChild(treeIndex); |
| |
| buildSegmentTree(leftTreeIndex, l, mid); |
| buildSegmentTree(rightTreeIndex, mid + 1, r); |
| |
| tree[treeIndex] = tree[leftTreeIndex] + tree[rightTreeIndex]; |
| } |
| |
| public void update(int index, int val) { |
| if (index < 0 || index >= data.length) { |
| throw new IllegalArgumentException("index is illegal."); |
| } |
| if (data[index] == val) return; |
| |
| data[index] = val; |
| update(0, 0, data.length - 1, index, val); |
| } |
| |
| private void update(int treeIndex, int l, int r, int index, int val) { |
| if (l == r) { |
| tree[treeIndex] = val; |
| return; |
| } |
| |
| int mid = l + (r - l) / 2; |
| int leftTreeIndex = leftChild(treeIndex); |
| int rightTreeIndex = rightChild(treeIndex); |
| |
| if (index <= mid) update(leftTreeIndex, l, mid, index, val); |
| else update(rightTreeIndex, mid + 1, r, index, val); |
| |
| tree[treeIndex] = tree[leftTreeIndex] + tree[rightTreeIndex]; |
| } |
| |
| public int sumRange(int left, int right) { |
| |
| if (left < 0 || left >= data.length || right < 0 || right >= data.length || left > right) { |
| throw new IllegalArgumentException("index is illegal."); |
| } |
| return query(0, 0, data.length - 1, left, right); |
| } |
| |
| private int query(int treeIndex, int l, int r, int queryL, int queryR) { |
| if (l == queryL && r == queryR) { |
| return tree[treeIndex]; |
| } |
| |
| int mid = l + (r - l) / 2; |
| int leftTreeIndex = leftChild(treeIndex); |
| int rightTreeIndex = rightChild(treeIndex); |
| |
| if (queryR <= mid) return query(leftTreeIndex, l, mid, queryL, queryR); |
| else if (queryL >= mid + 1) return query(rightTreeIndex, mid + 1, r, queryL, queryR); |
| else { |
| int leftSum = query(leftTreeIndex, l, mid, queryL, mid); |
| int rightSum = query(rightTreeIndex, mid + 1, r, mid + 1, queryR); |
| return leftSum + rightSum; |
| } |
| } |
| |
| private int leftChild(int index) { |
| return index * 2 + 1; |
| } |
| |
| private int rightChild(int index) { |
| return index * 2 + 2; |
| } |
| } |
8.3、实现前缀树
208 - 实现 Trie(前缀树)
| public class Trie { |
| |
| private class Node { |
| public boolean isWord; |
| public TreeMap<Character, Node> next; |
| |
| public Node(boolean isWord) { |
| this.isWord = isWord; |
| this.next = new TreeMap<>(); |
| } |
| |
| public Node() { |
| this(false); |
| } |
| } |
| |
| private final Node root; |
| |
| public Trie() { |
| root = new Node(); |
| } |
| |
| public void insert(String word) { |
| Node cur = root; |
| |
| for (int i = 0; i < word.length(); i++) { |
| char c = word.charAt(i); |
| if (!cur.next.containsKey(c)) cur.next.put(c, new Node()); |
| cur = cur.next.get(c); |
| } |
| |
| if (!cur.isWord) cur.isWord = true; |
| } |
| |
| public boolean search(String word) { |
| Node cur = root; |
| |
| for (int i = 0; i < word.length(); i++) { |
| char c = word.charAt(i); |
| if (!cur.next.containsKey(c)) return false; |
| cur = cur.next.get(c); |
| } |
| |
| return cur.isWord; |
| } |
| |
| public boolean startsWith(String prefix) { |
| Node cur = root; |
| |
| for (int i = 0; i < prefix.length(); i++) { |
| char c = prefix.charAt(i); |
| if (!cur.next.containsKey(c)) return false; |
| cur = cur.next.get(c); |
| } |
| |
| return true; |
| } |
| } |
8.4、添加与搜索单词
211 - 添加与搜索单词 - 数据结构设计
| public class WordDictionary { |
| |
| private class Node { |
| public boolean isWord; |
| public TreeMap<Character, Node> next; |
| |
| public Node(boolean isWord) { |
| this.isWord = isWord; |
| this.next = new TreeMap<>(); |
| } |
| |
| public Node() { |
| this(false); |
| } |
| } |
| |
| private final Node root; |
| |
| public WordDictionary() { |
| root = new Node(); |
| } |
| |
| public void addWord(String word) { |
| Node cur = root; |
| |
| for (int i = 0; i < word.length(); i++) { |
| char c = word.charAt(i); |
| if (!cur.next.containsKey(c)) cur.next.put(c, new Node()); |
| cur = cur.next.get(c); |
| } |
| |
| if (!cur.isWord) cur.isWord = true; |
| } |
| |
| public boolean search(String word) { |
| return match(root, word, 0); |
| } |
| |
| |
| |
| |
| |
| private boolean match(Node node, String word, int index) { |
| if (index == word.length()) return node.isWord; |
| |
| char c = word.charAt(index); |
| |
| if (c != '.') { |
| if (!node.next.containsKey(c)) return false; |
| return match(node.next.get(c), word, index + 1); |
| } else { |
| for (Node nextNode : node.next.values()) { |
| if (match(nextNode, word, index + 1)) return true; |
| } |
| return false; |
| } |
| } |
| } |
8.5、键值映射
677 - 键值映射
| public class MapSum { |
| |
| private class Node { |
| public int val; |
| public TreeMap<Character, Node> next; |
| |
| public Node(int val) { |
| this.val = val; |
| next = new TreeMap<>(); |
| } |
| |
| public Node() { |
| this(0); |
| } |
| } |
| |
| private final Node root; |
| |
| public MapSum() { |
| root = new Node(); |
| } |
| |
| public void insert(String word, int val) { |
| Node cur = root; |
| |
| for (int i = 0; i < word.length(); i++) { |
| char c = word.charAt(i); |
| if (!cur.next.containsKey(c)) cur.next.put(c, new Node()); |
| cur = cur.next.get(c); |
| } |
| |
| cur.val = val; |
| } |
| |
| public int sum(String prefix) { |
| Node cur = root; |
| |
| for (int i = 0; i < prefix.length(); i++) { |
| char c = prefix.charAt(i); |
| if (!cur.next.containsKey(c)) return 0; |
| cur = cur.next.get(c); |
| } |
| |
| return sum(cur); |
| } |
| |
| private int sum(Node node) { |
| int sum = node.val; |
| if (node.next.isEmpty()) return sum; |
| |
| for (Node nextNode : node.next.values()) sum += sum(nextNode); |
| return sum; |
| } |
| } |
9、week13
9.1、字符串中的第一个唯一字符
387 - 字符串中的第一个唯一字符
| public int firstUniqChar(String s) { |
| int[] freq = new int[26]; |
| |
| for (int i = 0; i < s.length(); i++) freq[s.charAt(i) - 'a']++; |
| |
| for (int i = 0; i < s.length(); i++) { |
| if (freq[s.charAt(i) - 'a'] == 1) return i; |
| } |
| |
| return -1; |
| } |
9.2、区域和检索 II
307 - 区域和检索 - 数组可修改
| public class NumArray { |
| |
| private int[] data; |
| private int[] blocks; |
| private int N; |
| private int B; |
| private int Bn; |
| |
| public NumArray(int[] nums) { |
| N = nums.length; |
| if (N == 0) return; |
| |
| B = (int) Math.sqrt(N); |
| Bn = N / B + (N % B != 0 ? 1 : 0); |
| |
| data = Arrays.copyOf(nums, N); |
| blocks = new int[Bn]; |
| for (int i = 0; i < N; i++) blocks[i / B] += data[i]; |
| } |
| |
| public void update(int index, int val) { |
| if (index < 0 || index >= N) return; |
| int diff = val - data[index]; |
| data[index] = val; |
| blocks[index / B] += diff; |
| } |
| |
| public int sumRange(int l, int r) { |
| if (l < 0 || l >= N || r < 0 || r >= N || l > r) return 0; |
| |
| int sum = 0; |
| int bStart = l / B; |
| int bEnd = r / B; |
| |
| if (Math.abs(bStart - bEnd) <= 1) { |
| for (int i = l; i <= r; i++) sum += data[i]; |
| } else { |
| for (int i = l; i < (bStart + 1) * B; i++) sum += data[i]; |
| for (int i = bStart + 1; i < bEnd; i++) sum += blocks[i]; |
| for (int i = bEnd * B; i <= r; i++) sum += data[i]; |
| } |
| |
| return sum; |
| } |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步