LeetCode 910 - Smallest Range II


Related: LeetCode 908 - Smallest Range I
LeetCode 910 - Smallest Range II
https://leetcode.com/problems/smallest-range-ii/
Given an array A of integers, for each integer A[i] we need to choose either x = -K or x = K, and add x to A[i] (only once).
After this process, we have some array B.
Return the smallest possible difference between the maximum value of B and the minimum value of B.
    Example 1:
    Input: A = [1], K = 0
    Output: 0
    Explanation: B = [1]
    
    Example 2:
    Input: A = [0,10], K = 2
    Output: 6
    Explanation: B = [2,8]
    
    Example 3:
    Input: A = [1,3,6], K = 3
    Output: 3
    Explanation: B = [4,6,3]
    
    http://www.noteanddata.com/leetcode-910-Smallest-Range-II-solution-note.html
    https://www.acwing.com/solution/LeetCode/content/718/
    我们肯定期望在较小的数字上增加 K,在较大的数组上减少 K,所以首先将数组 A 从小到大排序。
    初始化答案为 A[n - 1] - A[0];然后依次枚举每个位置 i,计算此时的最小值 min(A[0] + K, A[i + 1] - K) 和最大值 max(A[i] + K, A[n - 1] - K),然后更新答案。
    https://blog.csdn.net/XX_123_1_RJ/article/details/82850678
    这个题目还是比较有意思的,看了评论才搞明白,排序,然后线性扫描就可以得出结果。
    (1)先有这样一个知识,假设a < b,那么[a + k, b - k],一定是[a - k, b + k]的一个子集,后面的计算,就可以在[a + k, b - k] 区间里面寻找了。
    (2)首先对整个数组从小到大排序,方便后面计算,并且确定一个上界 res = A[-1] - A[0] (其中这个上界,包含了两个数同时加上或者减轻 K的情况)。
    (3)排序后,来看一种情况,假设数组A在i处被分割为两部分[ A[1], A[2], A[3]... A[i] ]、[ A[i+1], A[i+2], A[i+3]... A[n-1] ] 现在可以把这两部分,看成两个值,然后考虑(1)中的情况,遍历选出最优的结果。如果说存在贪心思想,感觉,在选取i的情况下,可以说是贪心的选取得
    https://www.cnblogs.com/pk28/p/9696276.html
    贪心,先排序,然后结果肯定是选个位置pos,pos之前的元素都+k之后的元素都-k,那么我们就枚举这个位置,然后进行判断,首先pos这个位置一定是把数组分成两个递增的序列,那么我们枚举4个值就可以了

    As in Smallest Range I, smaller A[i] will choose to increase their value ("go up"), and bigger A[i] will decrease their value ("go down").
    Algorithm
    We can formalize the above concept: if A[i] < A[j], we don't need to consider when A[i] goes down while A[j] goes up. This is because the interval (A[i] + K, A[j] - K) is a subset of (A[i] - K, A[j] + K) (here, (a, b) for a > b denotes (b, a) instead.)
    That means that it is never worse to choose (up, down) instead of (down, up). We can prove this claim that one interval is a subset of another, by showing both A[i] + K and A[j] - K are between A[i] - Kand A[j] + K.
    For sorted A, say A[i] is the largest i that goes up. Then A[0] + K, A[i] + K, A[i+1] - K, A[A.length - 1] - K are the only relevant values for calculating the answer: every other value is between one of these extremal values.
        public int smallestRangeII(int[] A, int K) {
            int N = A.length;
            Arrays.sort(A);
            int ans = A[N-1] - A[0];

            for (int i = 0; i < A.length - 1; ++i) {
                int a = A[i], b = A[i+1];
                int high = Math.max(A[N-1] - K, a + K);
                int low = Math.min(A[0] + K, b - K);
                ans = Math.min(ans, high - low);
            }
            return ans;
        }
    https://leetcode.com/problems/smallest-range-ii/discuss/173505/Java-Solution-with-the-Picture-to-explain-it
    We can use greedy algorithm to solve this problem and the best status each time is bipartite, which means every element from left + K and every element from right - K. Firstly, we need to sort the Array. And, we can assume all the numbers array A - K. So, we can get the initial candidate. Then we increase the number of elements that + K and each status will update min & max and the candidate.
    j = i + 1
    
      i j
      o----
    ----o
      ----o
         ----o
            ----o
    
        i j
      o----
        o----
      ----o
         ----o
            ----o
            
          i  j  
      o----
        o----
          o----
         ----o
            ----o
    
    
             i  j  
      o----
        o----
          o----
             o----
            ----o
    
        public int smallestRangeII(int[] A, int K) {
            Arrays.sort(A);
            int n = A.length;
            int res = A[n - 1] - A[0];
            for (int i = 0; i < n - 1; i++) {
                int max = Math.max(A[i] + K, A[n - 1] - K);
                int min = Math.min(A[i + 1] - K, A[0] + K);
                res = Math.min(res, max - min);
            }
            return res;
        }
    

    https://leetcode.com/problems/smallest-range-ii/discuss/173389/simple-C%2B%2B-solution-with-explanation
    • Sort the vector.
    • Assuming there is a point, on the left of the point, all elements add K, on the right of the point, all elements substract K, check each possible point. (a point is between two numbers).
    • Cause there are two segments (A[0]+K, A[1]+K, ..., A[i]+K, A[i+1]-K, ..., A[n]-K), the first one is on the left of the current point (A[i] + K is the last element of the first segment), the second one is on the right of the current point (A[i + 1] - K is the first element of the second segment). For the first segment, the smallest element is left, the largest is A[i] + K; For the second segment, A[i + 1] - K is the smallest element, the largest is right. Thus, for each point, the largest element should be either A[i] + K or right, the smallest element should be either left or A[i + 1] - K.
        int smallestRangeII(vector<int>& A, int K) {
            sort(A.begin(), A.end());
            int res = A[A.size() - 1] - A[0];
            int left = A[0] + K, right = A[A.size() - 1] - K;
            for (int i = 0; i < A.size() - 1; i++) {
                int maxi = max(A[i] + K, right), mini = min(left, A[i + 1] - K);
                res = min(res, maxi - mini);
            }
            return res;
        }
    

    https://leetcode.com/problems/smallest-range-ii/discuss/173377/C%2B%2BJavaPython-Add-0-or-2-*-K

    For each integer A[i],
    we may choose either x = -K or x = K.
    If we add K to all B[i], the result won't change.
    It's the same as:
    For each integer A[i], we may choose either x = 0 or x = 2 * K.

    Explanation:

    We sort the A first, and we choose to add x = 0 to all A[i].
    Now we have res = A[n - 1] - A[0].
    Starting from the smallest of A, we add 2 * K to A[i],
    hoping this process will reduce the difference.
    Update the new mx = max(mx, A[i] + 2 * K)
    Update the new mn = min(A[i + 1], A[0] + 2 * K)
    Update the res = min(res, mx - mn)

        public int smallestRangeII(int[] A, int K) {
            Arrays.sort(A);
            int n = A.length, mx = A[n - 1], mn = A[0], res = mx - mn;
            for (int i = 0; i < n - 1; ++i) {
                mx = Math.max(mx, A[i] + 2 * K);
                mn = Math.min(A[i + 1], A[0] + 2 * K);
                res = Math.min(res, mx - mn);
            }
            return res;
        }
    


    Q: Do we have to sort the list?
    A: In general cases, Yes. and this can be easily proved.
    For example A = [0,1,4,5,6,7,8,9], K = 5
    result = 2 * K - max(gap between numbers) = 2 * 5 - (4 - 1) = 7
    To get the gap of consecutive numbers (in sorted order),
    so in fact, this problem has no difference from 164. Maximum Gap
    I don't have a better idea than sort.
    But we don't have to use promitif O(NlogN) sort.
    Other O(N) sort like bucket sort can be apllied to this problem.
    Q: Except the general cases, do we any corner case?
    A: Yes
    if max(A) - min(A) >= 4 * K, return max(A) - min(A) - 2 * K
    if max(A) - min(A) <= K, return max(A) - min(A)
    Otherwise, we have to sort.
    Q: Can we optimise this O(NlogN) solution?
    A:
    Optimization 1, Apply O(N) sort
    Reference to 164. Maximum Gap.
    Optimization 2, Sort only one part of whole list
    To be easier understood, I sort the whole list here.
    But we don't have to.
    We can only take and sort he number between [max(A) - 2 * K, min(A) + 2 * K]
    This will help improve the complexity a lot.
    In 30 of 68 total cases, we solve the problem in O(N).
    In ther rest cases, we solve in O(KlogK) where K <= N.
    Example in python, it will improve from 120ms to 45ms.
        def smallestRangeII(self, A, K):
            ma, mi = max(A), min(A)
            if ma - mi >= 4 * K: return ma - mi - 2 * K
            if ma - mi <= K: return ma - mi
            inter = sorted([i for i in A if ma - 2 * K < i < mi + 2 * K] + [ma - 2 * K, mi + 2 * K])
            return min(a + 2 * K - b for a, b in zip(inter, inter[1:]))
    

    https://leetcode.com/problems/smallest-range-ii/discuss/173471/JAVA-solution-very-easy-to-understand-sliding-window
        public int smallestRangeII(int[] A, int K) {
            if (A == null || A.length < 2) {
                return 0;
            }
            
            List<int[]> candidates = new ArrayList<int[]>();
            for (int i = 0; i < A.length; i++) {
                candidates.add(new int[]{i, A[i] - K});
                candidates.add(new int[]{i, A[i] + K});
            }
            
            // sliding window to let the window contains all indexes from A
            Collections.sort(candidates, (x1, x2) -> {
                return x1[1] < x2[1] ? -1 : 1;
            });
            
            int result = Integer.MAX_VALUE;
            Map<Integer, Integer> map = new HashMap<Integer, Integer>();
            int left = 0, right = 0;
            while (right < candidates.size()) {
                // move right until contains all indexes
                while (right < candidates.size() && map.size() < A.length) {
                    int index = candidates.get(right)[0];
                    if (!map.containsKey(index)) {
                        map.put(index, 0);
                    }
                    map.put(index, map.get(index) + 1);
                    right++;
                }
                
                int newRight = right;
                right--;
                
                // move left until has space to move right
                while (left < right && map.size() >= A.length) {
                    result = Math.min(result, candidates.get(right)[1] - candidates.get(left)[1]);
                    int index = candidates.get(left)[0];
                    map.put(index, map.get(index) - 1);
                    if (map.get(index) == 0) {
                        map.remove(index);
                    }
                    left++;
                }
                
                right = newRight;
            }
            return result;
        }
    

    https://leetcode.com/problems/smallest-range-ii/discuss/174928/c%2B%2B-O(n)-time-solution!-Take-the-challenge!-With-very-very-detail-description-and-comments

    Labels

    LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

    Popular Posts