LeetCode 967 - Numbers With Same Consecutive Differences


https://leetcode.com/problems/numbers-with-same-consecutive-differences/
Return all non-negative integers of length N such that the absolute difference between every two consecutive digits is K.
Note that every number in the answer must not have leading zeros except for the number 0 itself. For example, 01 has one leading zero and is invalid, but 0 is valid.
You may return the answer in any order.

Example 1:
Input: N = 3, K = 7
Output: [181,292,707,818,929]
Explanation: Note that 070 is not a valid number, because it has leading zeroes.
Example 2:
Input: N = 2, K = 1
Output: [10,12,21,23,32,34,43,45,54,56,65,67,76,78,87,89,98]
Note:
  1. 1 <= N <= 9
  2. 0 <= K <= 9
https://www.acwing.com/solution/LeetCode/content/697/
(递归) O(2^N)
采用递归的方式,从高位开始逐一填数字,除最高位外,每一位最多有两种填法,分别尝试即可。
时间复杂度
最坏情况下,除最高位外,每一位都有两种填法,故时间复杂度为 O(2^N)

https://www.cnblogs.com/seyjs/p/10201645.html
但是有两点要注意的,一是K = 0 的情况会造成重复(+0和-0的值一样),二是N等于1的时候,别忘了0也是其中一个结果。
X. BFS
https://leetcode.com/problems/numbers-with-same-consecutive-differences/discuss/211183/JavaC%2B%2BPython-Iterative-Solution
We initial the current result with all 1-digit numbers,
like cur = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].
Each turn, for each x in cur,
we get its last digit y = x % 10.
If y + K < 10, we add x * 10 + y + K to the new list.
If y - K >= 0, we add x * 10 + y + K to the new list.
We repeat this step N - 1 times and return the final result.
    public int[] numsSameConsecDiff(int N, int K) {
        List<Integer> cur = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
        for (int i = 2; i <= N; ++i) {
            List<Integer> cur2 = new ArrayList<>();
            for (int x : cur) {
                int y = x % 10;
                if (x > 0 && y + K < 10)
                    cur2.add(x * 10 + y + K);
                if (x > 0 && K > 0 && y - K >= 0)
                    cur2.add(x * 10 + y - K);
            }
            cur = cur2;
        }
        return cur.stream().mapToInt(j->j).toArray();
    }

Let's try to write some number in the answer digit by digit.
For each digit except the first, there are at most 2 choices for that digit. This means that there are at most 9 * 2^8 possible 9 digit numbers, for example. This is small enough to brute force.
An 
N digit number is just an N-1 digit number with a final digit added. If the N-1 digit number ends in a digit d, then the N digit number will end in d-K or d+K (provided these are digits in the range [0,9]). We store these numbers in a Set structure to avoid duplicates.
Also, we should be careful about leading zeroes -- only 1 digit numbers will start with 0.
  • Time Complexity: O(2^N).
  • Space Complexity: O(2^N).
  public int[] numsSameConsecDiff(int N, int K) {
    Set<Integer> cur = new HashSet();
    for (int i = 1; i <= 9; ++i)
      cur.add(i);

    for (int steps = 1; steps <= N - 1; ++steps) {
      Set<Integer> cur2 = new HashSet();
      for (int x : cur) {
        int d = x % 10;
        if (d - K >= 0)
          cur2.add(10 * x + (d - K));
        if (d + K <= 9)
          cur2.add(10 * x + (d + K));
      }

      cur = cur2;
    }

    if (N == 1)
      cur.add(0);

    int[] ans = new int[cur.size()];
    int t = 0;
    for (int x : cur)
      ans[t++] = x;
    return ans;

  }
X.  Using Queue
https://leetcode.com/problems/numbers-with-same-consecutive-differences/discuss/211433/Java-11-liner-BFSBacktrack
  1. Initialize a queue with the most significant digits of candidate numbers: [1, 2, 3, 4, 5, 6, 7, 8, 9]; if N is 1, add 0 to the queue.
  2. During every round of breadth search, the last digit of any given number, num, is k = num % 10.
    If digit1 = k - K >= 0, append it to the end of num;
    If digit2 = k + K < 10, and digit1 != digit2, append it to the end of num;
  3. Repeat the above N - 1 times.
    public int[] numsSameConsecDiff(int N, int K) {
        Queue<Integer> q = new LinkedList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9));
        if (N == 1) { q.offer(0); } // in case N is 1.
        while (N-- > 1) {
            for (int sz = q.size(); sz > 0; --sz) {
                int num = q.poll();
                int digit1 = num % 10 - K, digit2 = num % 10 + K;
                if (digit1 >= 0) { q.offer(num * 10 + digit1); }
                if (digit2 < 10 && digit1 != digit2) { q.offer(num * 10 + digit2); }
            }
        }
        return q.stream().mapToInt(i -> i).toArray();
    }


X. DFS
https://leetcode.com/problems/numbers-with-same-consecutive-differences/discuss/211346/Simple-backtracking-with-explanation
this simply falls into backtracking problem template.
At each point, we can potentially:
  1. add K to current digit
  2. subtract k from current digit
and move to next step.
one edge case is to make sure that nextPlusK and nextMinusK hold different values, otherwise, there will be duplicate in the final results.
    public int[] numsSameConsecDiff(int N, int K) {
        
        ArrayList<Integer> allRes = new ArrayList();
        
        int begin = N == 1 ? 0 : 1;
        for (int i = begin; i <= 9 ; i++){
            backtrack(N, K, i, 0, i, allRes);
        }
        
        // copy to array
        return allRes.stream().mapToInt(j->j).toArray();
    }
    
    private void backtrack(int N, int K, int cur, int idx, int prev, ArrayList<Integer> allRes) {
        
        if (idx == N - 1) {
            allRes.add(cur);
            return;
        }
        
        int nextPlusK = prev + K;
        if (nextPlusK < 10){
            
            backtrack(N, K, (cur * 10) + nextPlusK, idx + 1, nextPlusK, allRes);
        }
        int nextMinusK = prev - K;
        
        if (nextMinusK != nextPlusK && nextMinusK >= 0){
            
            backtrack(N, K, (cur * 10) + nextMinusK, idx + 1, nextMinusK, allRes);
        }
    }
https://www.acwing.com/solution/LeetCode/content/697/
    void solve(int depth, int num, int N, int K, vector<int> &ans) {
        if (depth == 0) {
            ans.push_back(num);
            return;
        }

        if (depth == N) {
            for (int i = 1; i <= 9; i++)
                solve(depth - 1, i, N, K, ans);
            if (N == 1)
                solve(depth - 1, 0, N, K, ans);
        }

        else {
            int last = num % 10;

            if (last + K <= 9)
                solve(depth - 1, num * 10 + last + K, N, K, ans);

            if (K != 0 && last - K >= 0)
                solve(depth - 1, num * 10 + last - K, N, K, ans);
        }

    }

    vector<int> numsSameConsecDiff(int N, int K) {
        vector<int> ans;
        solve(N, 0, N, K, ans);

        return ans;
    }

Keep adding digits from 0 to 9 to a temporary integer at units place. Before adding we check if the digit being added is satisfying the condition of differing with previous digit by K. We add untill the temporary integer has N digits in it.
Start with the dfs function
  1. fill the base cases first.
  • If the Number has enough digits, add it to the final list.
  • When the temporary integer is empty add all the digits except 0.
  1. Later, fill the recursion for dfs.
  2. Think about handling edge cases - What should be returned if N = 0, N = 1 (where 0 should appear in end result) or K = 1 ?
public int[] numsSameConsecDiff(int N, int K) {
        List<Integer> list = new ArrayList<>();
        if(N==0)
            return new int[0];
        if(N==1)
   list.add(0);      // edge case
        dfs(N, K, list, 0);
        return list.stream().mapToInt(i->i).toArray();   //list.toArray(new int[list.size()]); doesn't work for primitives
    }
    public void dfs(int N, int K, List<Integer> list, int number){
        if(N == 0){   // base case, if you have added enough number of integers then append it to list; Here N is used as the total digits in temporary number 
            list.add(number);
            return ;
        }
        for(int i=0; i<10; ++i){
            if(i==0 && number ==0)    // Do not add 0 at begining of a number
                continue;
            else if(number == 0 && i!=0){     // base case, we add all the digits when we do not have any previous digit to check if difference = K
                dfs(N-1, K, list, i);
            }
            else{
                if(Math.abs((number%10) - i )==K){
                    dfs(N-1, K, list, number*10+i);    // General dfs to add the digit at the units place and reducing the number of digits by 1.
                }
            }
        }
    }

X. https://leetcode.com/problems/numbers-with-same-consecutive-differences/discuss/211346/Simple-backtracking-with-e
At each point, we can potentially:
  1. add K to current digit
  2. subtract k from current digit
and move to next step.

one edge case is to make sure that nextPlusK and nextMinusK hold different values, otherwise, there will be duplicate in the final results.
    public int[] numsSameConsecDiff(int N, int K) {
        
        ArrayList<Integer> allRes = new ArrayList();
        
        int begin = N == 1 ? 0 : 1;
        for (int i = begin; i <= 9 ; i++){
            backtrack(N, K, i, 0, i, allRes);
        }
        
        // copy to array
        return allRes.stream().mapToInt(j->j).toArray();
    }
    
    private void backtrack(int N, int K, int cur, int idx, int prev, ArrayList<Integer> allRes) {
        
        if (idx == N - 1) {
            allRes.add(cur);
            return;
        }
        
        int nextPlusK = prev + K;
        if (nextPlusK < 10){
            
            backtrack(N, K, (cur * 10) + nextPlusK, idx + 1, nextPlusK, allRes);
        }
        int nextMinusK = prev - K;
        
        if (nextMinusK != nextPlusK && nextMinusK >= 0){
            
            backtrack(N, K, (cur * 10) + nextMinusK, idx + 1, nextMinusK, allRes);
        }
    }

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