LeetCode 799 - Champagne Tower


https://leetcode.com/problems/champagne-tower/description/
We stack glasses in a pyramid, where the first row has 1 glass, the second row has 2 glasses, and so on until the 100th row.  Each glass holds one cup (250ml) of champagne.
Then, some champagne is poured in the first glass at the top.  When the top most glass is full, any excess liquid poured will fall equally to the glass immediately to the left and right of it.  When those glasses become full, any excess champagne will fall equally to the left and right of those glasses, and so on.  (A glass at the bottom row has it's excess champagne fall on the floor.)
For example, after one cup of champagne is poured, the top most glass is full.  After two cups of champagne are poured, the two glasses on the second row are half full.  After three cups of champagne are poured, those two cups become full - there are 3 full glasses total now.  After four cups of champagne are poured, the third row has the middle glass half full, and the two outside glasses are a quarter full, as pictured below.
Now after pouring some non-negative integer cups of champagne, return how full the j-th glass in the i-th row is (both i and j are 0 indexed.)

Example 1:
Input: poured = 1, query_glass = 1, query_row = 1
Output: 0.0
Explanation: We poured 1 cup of champange to the top glass of the tower (which is indexed as (0, 0)). There will be no excess liquid so all the glasses under the top glass will remain empty.

Example 2:
Input: poured = 2, query_glass = 1, query_row = 1
Output: 0.5
Explanation: We poured 2 cups of champange to the top glass of the tower (which is indexed as (0, 0)). There is one cup of excess liquid. The glass indexed as (1, 0) and the glass indexed as (1, 1) will share the excess liquid equally, and each will get half cup of champange.

Note:
  • poured will be in the range of [0, 10 ^ 9].
  • query_glass and query_row will be in the range of [0, 99].

X. DP
Instead of keeping track of how much champagne should end up in a glass, keep track of the total amount of champagne that flows through a glass. For example, if poured = 10 cups are poured at the top, then the total flow-through of the top glass is 10; the total flow-through of each glass in the second row is 4.5, and so on.
Algorithm
In general, if a glass has flow-through X, then Q = (X - 1.0) / 2.0 quantity of champagne will equally flow left and right. We can simulate the entire pour for 100 rows of glasses. A glass at (r, c) will have excess champagne flow towards (r+1, c) and (r+1, c+1).
  • Time Complexity: O(R^2), where R is the number of rows. As this is fixed, we can consider this complexity to be O(1).
  • Space Complexity: O(R^2), or O(1) by the reasoning above.
    public double champagneTower(int poured, int query_row, int query_glass) {
        double[][] A = new double[102][102];
        A[0][0] = (double) poured;
        for (int r = 0; r <= query_row; ++r) {
            for (int c = 0; c <= r; ++c) {
                double q = (A[r][c] - 1.0) / 2.0;
                if (q > 0) {
                    A[r+1][c] += q;
                    A[r+1][c+1] += q;
                }
            }
        }

        return Math.min(1, A[query_row][query_glass]);
    }

https://leetcode.com/problems/champagne-tower/discuss/118711/JavaC%2B%2BPython-1D-DP-O(R)-space
Time O(R^2) Time, Space O(R), where R = query_row


    public double champagneTower(int poured, int query_row, int query_glass) {
        double[] res = new double[query_row + 2];
        res[0] = poured;
        for (int row = 1; row <= query_row; row++)
            for (int i = row; i >= 0; i--)
                res[i + 1] += res[i] = Math.max(0.0, (res[i] - 1) / 2);
        return Math.min(res[query_glass], 1.0);
    }
https://leetcode.com/problems/champagne-tower/discuss/118692/9ms-5-Lines-Code-C%2B%2BJava
public double champagneTower(int poured, int query_row, int query_glass) {
    double[] dp = new double[101]; dp[0] = poured;
    for(int row=1; row<=query_row; row++)
        for(int i=row; i>=0; i--)
            dp[i+1] += dp[i] = Math.max(0.0, (dp[i]-1)/2);
    return Math.min(dp[query_glass], 1.0);
}

http://zxi.mytechroad.com/blog/dynamic-programming/leetcode-799-champagne-tower/
define dp[i][j] as the volume of champagne will be poured into the j -th glass in the i-th row, dp[i][j] can be greater than 1.
Init dp[0][0] = poured.
Transition: if dp[i][j] > 1, it will overflow, the overflow part will be evenly distributed to dp[i+1][j], dp[i+1][j+1]
if dp[i][j] > 1:
dp[i+1][j] += (dp[i][j] – 1) / 2.0
dp[i+1][j + 1] += (dp[i][j] – 1) / 2.0
Answer: min(1.0, dp[query_row][query_index])
double champagneTower(int poured, int query_row, int query_glass) {
  constexpr int kRows = 100;
  vector<vector<double>> dp(kRows, vector<double>(kRows));
  dp[0][0] = poured;
  for (int i = 0; i < kRows - 1; ++i)
    for (int j = 0; j <= i; ++j)
      if (dp[i][j] > 1) {
        dp[i + 1][j    ] += (dp[i][j] - 1) / 2.0;
        dp[i + 1][j + 1] += (dp[i][j] - 1) / 2.0;
        dp[i][j] = 1.0;
      }
  return std::min(1.0, dp[query_row][query_glass]);
}
Pull:
double champagneTower(int poured, int query_row, int query_glass) {
   constexpr int kRows = 100;
  vector<vector<double>> dp(kRows, vector<double>(kRows));
  dp[0][0] = poured;
  for (int i = 1; i < kRows; ++i)
    for (int j = 0; j <= i; ++j) {
      if (j > 0) dp[i][j] += max(0.0, (dp[i - 1][j - 1] - 1) / 2.0);
      if (j < i) dp[i][j] += max(0.0, (dp[i - 1][j    ] - 1) / 2.0);
    }
  return std::min(1.0, dp[query_row][query_glass]);
}
https://www.cnblogs.com/grandyang/p/9286537.html
这道题用高脚杯摆了个金字塔,貌似在电影里见过这种酷炫的效果,不过好像还是3D的,组了个立体的酒杯金字塔。这道题中的金字塔是2D的,降低了一些难度。在我们最开始没有什么思路的时候,我们就从最简单的开始分析吧:
当只倒一杯酒的时候,只有最顶端的酒杯被填满。
当倒二杯酒的时候,最顶端的酒杯被填满,且第二层的两个酒杯各自装了一半。
当倒三杯酒的时候,最顶端的酒杯被填满,且第二层的两个酒杯也被填满。
当倒四杯酒的时候,最顶端的酒杯被填满,且第二层的两个酒杯也被填满,第三层的三个酒杯分别被填了四分之一,二分之一,和四分之一。
当倒五杯酒的时候,最顶端的酒杯被填满,且第二层的两个酒杯也被填满,第三层的三个酒杯分别被填了二分之一,填满,和二分之一。
...
如果酒是无限的,那么最终每个酒杯就会被填满,所以难点就是怎么知道在倒K杯酒后,当前的酒杯还剩多少。不管酒量又多大,当前酒杯最多只能装一杯,多余的酒都会流到下一行的两个酒杯。那么比如我们总共倒了五杯酒,那么最顶端的酒杯只能留住一杯,剩下的四杯全部均分到下行的酒杯中了,而离其最近的下一行的两个酒杯会平均分到其多出来的酒量。那么第二层的酒杯分别会得到(5-1)/2=2杯。而第二层的两个酒杯也分别只能留住一杯,各自多余的一杯还要往第三层流,那么第三层的第一个杯子接住了第二层的第一个杯子流下的半杯,而第三层的第二个杯子接住了第二层的两个杯子各自流下的半杯,于是填满了。第三层的第三个杯子接住了第二层的第二个杯子流下的半杯。那么我们的思路应该就是处理每一个杯子,将多余的酒量均分到其下一层对应的两个酒杯中,我们只需要处理到query_row那一行即可,如果地query_glass中的酒量超过一杯了,那么我们返回1就行了,因为多余的还会往下流,但我们不需要再考虑了。
我们建立一个二维的dp数组,其中dp[i][j]表示第i行第j列的杯子将要接住的酒量(可能大于1,因为此时还没有进行多余往下流的处理),那么我们就逐个遍历即可,将多余的酒量均分加入下一行的两个酒杯中即可
double champagneTower(int poured, int query_row, int query_glass) {
    vector<vector<double>> dp(101, vector<double>(101, 0));
    dp[0][0] = poured;
    for (int i = 0; i <= query_row; ++i) {
        for (int j = 0; j <= i; ++j) {
            if (dp[i][j] >= 1) {
                dp[i + 1][j] += (dp[i][j] - 1) / 2.0;
                dp[i + 1][j + 1] += (dp[i][j] - 1) / 2.0;
            }
        }
    }
    return min(1.0, dp[query_row][query_glass]);
}
我们可以对上面的代码进行空间上的优化,只用一个一维数组即可
double champagneTower(int poured, int query_row, int query_glass) {
    vector<double> dp(101, 0);
    dp[0] = poured;
    for (int i = 1; i <= query_row; ++i) {
        for (int j = i; j >= 0; --j) {
            dp[j + 1] += dp[j] = max(0.0, (dp[j] - 1) / 2.0);
        }
    }
    return min(1.0, dp[query_glass]);
}

X.  https://leetcode.com/problems/champagne-tower/discuss/191677/java-simulation
    public double champagneTower(int poured, int query_row, int query_glass) {
        double[][] g = new double[1 + query_row][1 + query_row];
        g[0][0] = poured;
        for (int i = 0; i < query_row; i++){
            for (int j = 0; j <= i; j++){
                if (g[i][j] > 1){
                    double p = (g[i][j] - 1.0) / 2;
                    g[i + 1][j] += p;
                    g[i + 1][j + 1] += p;
                }
            }
        }
        return Math.min(1.0, g[query_row][query_glass]);
    }

X. Videos
花花酱 LeetCode 799. Champagne Tower - 刷题找工作 EP173

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