LeetCode 6 - ZigZag Conversion



The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)
P   A   H   N
A P L S I I G
Y   I   R
And then read line by line: "PAHNAPLSIIGYIR"
Write the code that will take a string and make this conversion given a number of rows:
string convert(string text, int nRows);
convert("PAYPALISHIRING", 3) should return "PAHNAPLSIIGYIR".
https://discuss.leetcode.com/topic/3162/easy-to-understand-java-solution
Create nRows StringBuffers, and keep collecting characters from original string to corresponding StringBuffer. Just take care of your index to keep them in bound.
public String convert(String s, int nRows) {
    char[] c = s.toCharArray();
    int len = c.length;
    StringBuffer[] sb = new StringBuffer[nRows];
    for (int i = 0; i < sb.length; i++) sb[i] = new StringBuffer();
    
    int i = 0;
    while (i < len) {
        for (int idx = 0; idx < nRows && i < len; idx++) // vertically down
            sb[idx].append(c[i++]);
        for (int idx = nRows-2; idx >= 1 && i < len; idx--) // obliquely up
            sb[idx].append(c[i++]);
    }
    for (int idx = 1; idx < sb.length; idx++)
        sb[0].append(sb[idx]);
    return sb[0].toString();
}

https://leetcode.com/discuss/55208/if-you-are-confused-with-zigzag-pattern-come-and-see
/*n=numRows
Δ=2n-2    1                           2n-1                         4n-3
Δ=        2                     2n-2  2n                    4n-4   4n-2
Δ=        3               2n-3        2n+1              4n-5       .
Δ=        .           .               .               .            .
Δ=        .       n+2                 .           3n               .
Δ=        n-1 n+1                     3n-3    3n-1                 5n-5
Δ=2n-2    n                           3n-2                         5n-4
*/
that's the zigzag pattern the question asked! Be careful with nR=1 && nR=2
The size of every period is defined as "cycle"
cycle = (2*nRows - 2), except nRows == 1.
In this example, (2*nRows - 2) = 4.
In every period, every row has 2 elements, except the first row and the last row.
Suppose the current row is i, the index of the first element is j:
j = i + cycle*k, k = 0, 1, 2, ...
The index of the second element is secondJ:
secondJ = (j - i) + cycle - i
(j-i) is the start of current period, (j-i) + cycle is the start of next period.
string convert(string s, int nRows) { if(nRows <= 1) return s; string result = ""; //the size of a cycle(period) int cycle = 2 * nRows - 2; for(int i = 0; i < nRows; ++i) { for(int j = i; j < s.length(); j = j + cycle){ result = result + s[j]; int secondJ = (j - i) + cycle - i; if(i != 0 && i != nRows-1 && secondJ < s.length()) result = result + s[secondJ]; } } return result; }

http://n00tc0d3r.blogspot.com/2013/06/zigzag-conversion.html
  • For any full columns, the odd ones have nRows characters, even ones have(nRows - 2) characters.
  • For the first and last rows, we read one single character from each expended column;
  • For the rest of rows, we read two characters, one from top part and one from bottom part, from each expended column.
One edge case is that nRows = 1, where (nRows*2 - 2) becomes 0. In this case, we should simply return the original string.
 public String convert(String s, int nRows) {  
   if (nRows == 1) return s;  
   
   StringBuilder ss = new StringBuilder();  
   int n = nRows + nRows - 2;  
   // rest rows  
   for (int i = 0; i < nRows; ++i) {  
     int cur = i;  
     while (cur < s.length()) {  
       ss.append(s.charAt(cur));  
       cur += n;  
       if (i > 0 && i < nRows - 1 && (cur - i - i) < s.length()) {  
         ss.append(s.charAt(cur - i - i));  
       }  
     }  
   }  
   return ss.toString();  
 }
http://blog.csdn.net/linhuanmars/article/details/21145039
只要看出来他其实每个zigzag是2*m-2个字符就可以,这里m是结果的行的数量。接下来就是对于每一行先把往下走的那一列的字符加进去,然后有往上走的字符再加进去即可。时间复杂度是O(n),空间复杂度是O(1),代码如下: 
public String convert(String s, int nRows) {
    if(s == null || s.length()==0 || nRows <=0)
        return "";
    if(nRows == 1)
        return s;
    StringBuilder res = new StringBuilder();
    int size = 2*nRows-2;
    for(int i=0;i<nRows;i++)
    {
        for(int j=i;j<s.length();j+=size)
        {
            res.append(s.charAt(j));
            if(i!=0 && i!=nRows-1 && j+size-2*i<s.length())
                res.append(s.charAt(j+size-2*i));
        }                
    }
    return res.toString();
}
http://www.lifeincode.net/programming/leetcode-zigzag-conversion-java/
The number of rows is variable. So we need to find the rule of each row. For example, when nRows = 4, we know the ZigZag should be like the following.
It’s easy to find that the step of 4-number column is 6. In fact, the step is just two times of nRows minus 2, in which 2 indicating there  are no numbers between the 4-number column in the first line and last line.
And there is only one number between 4-number column in other lines. Take the second line as an example. The second line is “1 5 7 11 13 17 19”. We can take a look at “1 5 7”. The step between “1” and “5” is (nRows – 1 – 1) * 2, which is 4. And the step of “5” and “7” is 6 – 4 = 2. In fact, assuming we are at line i (starting at 0), the first step is (nRows – 1 – i) * 2.
We should be careful about the situation when nRows = 1. Because our formula is not suitable when nRows = 1. And the inner loop should start from i, not 0.
    public String convert(String s, int nRows) {
        if (nRows == 1)
            return s;
        StringBuilder builder = new StringBuilder();
        int step = 2 * nRows - 2;
        for (int i = 0; i < nRows; i++) {
            if (i == 0 || i == nRows - 1) {
                for (int j = i; j < s.length(); j = j + step) {
                    builder.append(s.charAt(j));
                }
            } else {
                int j = i;
                boolean flag = true;
                int step1 = 2 * (nRows - 1 - i);
                int step2 = step - step1;
                while (j < s.length()) {
                    builder.append(s.charAt(j));
                    if (flag)
                        j = j + step1;
                    else
                        j = j + step2;
                    flag = !flag;
                }
            }
        }
        return builder.toString();
    }

http://www.cnblogs.com/springfor/p/3889414.html
这道题就是看坐标的变化。并且需要分块处理。
 n=2时,字符串坐标变成zigzag的走法就是:
 0 2 4 6
 1 3 5 7
 n=3时的走法是:
 0     4     8
 1  3 5  7 9
 2     6    10 
 n=4时的走法是:
 0      6        12
 1   5 7    11 13
 2 4   8 10    14
 3      9         15 

 可以发现规律,画红色的长度永远是 2n-2 (想法是你试想把所有这些行压缩成两列,两边手挤一下,第二列永远的第一行和最后一行少字)。
 利用这个规律,可以按行填字,第一行和最后一行,就是按照2n-2的顺序一点点加的。
 其他行除了上面那个填字规则,就是还要处理斜着那条线的字,可以发现那条线的字的位置永远是当前列j+(2n-2)-2i(i是行的index)。 //????
public String convert(String s, int nRows) {  
 2         if(s == null || s.length()==0 || nRows <=0)
 3             return "";
 4         if(nRows == 1)
 5             return s;
 6           
 7         StringBuilder res = new StringBuilder();
 8         int size = 2*nRows-2;
 9         for(int i=0;i<nRows;i++){
10             for(int j=i;j<s.length();j+=size){
11                 res.append(s.charAt(j));
12                 if(i != 0 && i != nRows - 1){//except the first row and the last row
13                     int temp = j+size-2*i;
14                     if(temp<s.length())
15                         res.append(s.charAt(temp));
16                 }
17             }                
18         }
19         return res.toString();
20     } 
先计算一下每一个zig包含的字符个数,实际上是zigSize = nRows + nRows – 2
然后一行一行的加s中的特定元素就行。
第一行和最后一行都只需要加一个字符,每一个zig,而且在s中的index间隔是zigSize。
中间每一行需要添加两个字符到结果中去。第一个字符同上;第二个字符和前面添加这个字符在s上的inde相差正好是zigSize – 2*ir。ir是行index。
    string convert(string s, int nRows) {   
        if(nRows <= 1) return s;
        string ret;
        int zigsize = 2 * nRows - 2;
        for(int i = 0; i < nRows; ++i) {
            for(int base = i; ;base += zigsize) {
                if(base >= s.size())
                    break;
                ret.append(1,s[base]);
                if(i > 0 && i < nRows - 1) {
                    //middle need add ziggggging char
                    int ti = base + zigsize - 2 * i;
                    if(ti < s.size())
                        ret.append(1,s[ti]);
                }
            }
        }
        return ret;
    }
https://leetcode.com/discuss/10990/solutions-follows-order-string-follows-order-output-string
In the above sample case the number of rows is 4, when the first iteration is completed the locations 0,1,2,3 of the string builder gets filled with the locations 0,6,12,18 of the input string it goes on further for other three rows.
0 6 12 18 1 5 7 11 13 17 19 2 4 8 10 14 16 20 3 9 15 21
public String convert(String s, int nRows) { if (nRows == 1) return s; StringBuilder strBuilder = new StringBuilder(); int borderRowStep = 2 * nRows - 2; for (int i = 0; i < nRows; i++) { if (i == 0 || i == nRows - 1) { for (int j = i; j < s.length(); j = j + borderRowStep) { strBuilder.append(s.charAt(j)); } } else { int j = i; boolean flag = true; int insideRowLargeStep = 2 * (nRows - 1 - i); int insideRowSmallStep = borderRowStep - insideRowLargeStep; while (j < s.length()) { strBuilder.append(s.charAt(j)); if (flag) j = j + insideRowLargeStep; else j = j + insideRowSmallStep; flag = !flag; } } } return strBuilder.toString(); }
In the second version of algorithm string buffer is filled in the order of input string i.e, the string buffer gets filled in the zig zag order, when the first iteration of the outer while loop completes the locations 0,5,11,17 in string builder gets filled with the locations 0,1,2,3, from the input string
public String convert(String s, int nRows) { char[] c = s.toCharArray(); int len = c.length; StringBuffer[] sb = new StringBuffer[nRows]; for (int z=0; z < sb.length; z++) sb[z] = new StringBuffer(); int k=0; while (k < len) { for (int zigZagIndex = 0; zigZagIndex < nRows && k < len; zigZagIndex++) // vertically down sb[zigZagIndex].append(c[k++]); for (int zigZagIndex = nRows-2; zigZagIndex >= 1 && k < len; zigZagIndex--) // obliquely up sb[zigZagIndex].append(c[k++]); } for (int index = 1; index < sb.length; index++) sb[0].append(sb[index]);//\\ return sb[0].toString(); }
X. nRows StringBuilder - go down then go up
https://leetcode.com/discuss/10493/easy-to-understand-java-solution
Create nRows StringBuffers, and keep collecting characters from original string to corresponding StringBuffer. Just take care of your index to keep them in bound.
public String convert(String s, int nRows) {
    char[] c = s.toCharArray();
    int len = c.length;
    StringBuffer[] sb = new StringBuffer[nRows];
    for (int i = 0; i < sb.length; i++) sb[i] = new StringBuffer();

    int i = 0;
    while (i < len) {
        for (int idx = 0; idx < nRows && i < len; idx++) // vertically down
            sb[idx].append(c[i++]);
        for (int idx = nRows-2; idx >= 1 && i < len; idx--) // obliquely up
            sb[idx].append(c[i++]);
    }
    for (int idx = 1; idx < sb.length; idx++)
        sb[0].append(sb[idx]);//\\
    return sb[0].toString();
}
X.https://cheonhyangzhang.wordpress.com/2015/09/03/6-leetcode-java-zigzag-conversion-easy/
Use a delta flag to indicate whether next move should go up or go down.
    public String convert(String s, int nRows) {
        String[] helper = new String[nRows];
        for (int i = 0; i < nRows; i ++){
            helper[i] = "";
        }
        int row = 0;
        int delta = 1;
        for (int i = 0; i < s.length(); i ++){
            char c = s.charAt(i);
            helper[row] += c;
            if (row == nRows - 1){
                delta = -1;
            }
            else if (row == 0){
                delta = 1;
            }
            row = row + delta;
            row = Math.max(0, row);
        }//for
        String result = "";
        for (int i = 0; i < nRows && s.length() > 0; i ++){
            result += helper[i];
        }
        return result;
    }
X. O(1) space
https://discuss.leetcode.com/topic/21196/a-10-lines-one-pass-o-n-time-o-1-space-accepted-solution-with-detailed-explantation
The distribution of the elements is period.
P   A   H   N
A P L S I I G
Y   I   R
For example, the following has 4 periods(cycles):
P   | A   | H   | N
A P | L S | I I | G
Y   | I   | R   |
The size of every period is defined as "cycle"
cycle = (2*nRows - 2), except nRows == 1.
In this example, (2*nRows - 2) = 4.
In every period, every row has 2 elements, except the first row and the last row.
Suppose the current row is i, the index of the first element is j:
j = i + cycle*k, k = 0, 1, 2, ...
The index of the second element is secondJ:
secondJ = (j - i) + cycle - i
(j-i) is the start of current period, (j-i) + cycle is the start of next period.
string convert(string s, int nRows) {
        if(nRows <= 1) return s;
        string result = "";
        //the size of a cycle(period)
        int cycle = 2 * nRows - 2;
        for(int i = 0; i < nRows; ++i)
        {
            for(int j = i; j < s.length(); j = j + cycle){
               result = result + s[j];
               int secondJ = (j - i) + cycle - i;
               if(i != 0 && i != nRows-1 && secondJ < s.length())
                   result = result + s[secondJ];
            }
        }
        return result;
    }
https://gist.github.com/wayetan/8266559
    public String convert(String s, int nRows) {
        if(nRows <= 1)
            return s;
        StringBuilder[] list = new StringBuilder[nRows];
        for(int i = 0; i < nRows; i++)
            list[i] = new StringBuilder();
        int row = 0;
        int i = 0;
        boolean down = true;
        while(i < s.length()){
            list[row].append(s.charAt(i));
            if(row == 0)
                down = true;
            if(row == nRows - 1)
                down = false;
            if(down)
                row++;
            else
                row--;
            i++;
        }
        StringBuilder res = new StringBuilder();
        for(StringBuilder sb : list)
            res.append(sb.toString());
        return res.toString();
    }

http://www.cnblogs.com/TenosDoIt/p/3738693.html

Read full article from LeetCode - ZigZag Conversion | Darren's Blog

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