LeetCode-Algorithms #006 ZigZag Conversion, Database #180 Employees Earning More Than Their Managers
LeetCode-Algorithms #006 ZigZag Conversion
給定一個字符串, 以及需要輸出的行數, 將字符串按照給定行數進行Z字形排列(效果見上圖), 然後將得到的結果逐行拼接成一個新的字符串, 返回這個新串
我的思路:
通過給定的行數計算每一個字符在Z形排列中位於哪一行並不困難, 如果要求是排列為n行, 那麽原字符串中的字符所在的行數每前進2n-2個就會經歷一個循環
不難發現, 原字符串中的第i個字符只要滿足如下條件, 就必然在Z形排列的第n行出現:
i % (2 * numRows - 2) == n || i % (2 * numRows - 2) == (2 * numRows - 2 - n)
這樣, 遍歷後就可以得到各行的子串, 拼接後即可得到結果:
1 class Solution { 2 public String convert(String s, int numRows) { 3 //排除特殊情況 4 if(numRows == 1) return s; 5 //建立一個字符串存儲結果 6 String result = ""; 7 //把字符串轉化為字符數組 8 char[] arr = s.toCharArray(); 9 //獲取字符串長度 10int len = arr.length; 11 12 //分別獲取每一行中的字符 13 for (int n = 0; n < numRows; n++) { 14 //創建一個空串存儲每一行中的字符 15 String temp = ""; 16 //遍歷字符串數組, 把符合條件的字符存儲至temp中 17 for (int i = 0; i < len; i++) { 18 if (i % (2 * numRows - 2) == n || i % (2 * numRows - 2) == (2 * numRows - 2 - n)) {19 temp = temp + arr[i]; 20 } 21 } 22 //把temp添加到result中 23 result = result + temp; 24 } 25 //返回結果 26 return result; 27 } 28 }
這樣處理雖然非常直觀, 但是效率很低, n行的結果就需要對字符串進行n次遍歷, 顯然是很低效的
參考提示後對代碼進行修改:
1 class Solution { 2 public String convert(String s, int numRows) { 3 //排除特殊情況 4 if(numRows == 1) return s; 5 //把字符串轉化為字符數組 6 char[] arr = s.toCharArray(); 7 //獲取字符串長度 8 int len = arr.length; 9 //排除特殊情況 10 if(len<=numRows)return s; 11 //建立一個字符串存儲結果 12 String result = ""; 13 //建立一個StringBuilder的List存儲各行結果 14 List<StringBuilder> list = new ArrayList<>(); 15 for(int i = 0; i < numRows; i++) { 16 list.add(new StringBuilder()); 17 } 18 19 //將各個字符添加至應在的行 20 for(int index = 0; index < len; index++) { 21 int rowIndex = (index % (2*numRows -2)) < numRows ? (index % (2*numRows -2)) : (2*numRows -2)-(index % (2*numRows -2)); 22 list.get(rowIndex).append(arr[index]); 23 } 24 //組合結果 25 for (StringBuilder stringBuilder : list) { 26 result += stringBuilder.toString(); 27 } 28 //返回結果 29 return result; 30 } 31 }
這樣顯然節省了不少計算, 但是實際上並沒有快很多, 主要問題我想還是出在細節上, 比如能用StringBuilder.append的地方用了字符串拼接等等
看一看官方答案, 就漂亮多了:
1 class Solution { 2 public String convert(String s, int numRows) { 3 4 if (numRows == 1) return s; 5 6 List<StringBuilder> rows = new ArrayList<>(); 7 for (int i = 0; i < Math.min(numRows, s.length()); i++) 8 rows.add(new StringBuilder()); 9 10 int curRow = 0; 11 boolean goingDown = false; 12 13 for (char c : s.toCharArray()) { 14 rows.get(curRow).append(c); 15 if (curRow == 0 || curRow == numRows - 1) goingDown = !goingDown; 16 curRow += goingDown ? 1 : -1; 17 } 18 19 StringBuilder ret = new StringBuilder(); 20 for (StringBuilder row : rows) ret.append(row); 21 return ret.toString(); 22 } 23 }
用了一個指針來記錄遍歷到的字符應該在哪一行, 節省了不少計算
再來看另一種思路, 遍歷的過程和我最開始的方法近似, 但是每次不是每個字符都遍歷, 而是每添加一個字符就將指針後推一個循環:
1 class Solution { 2 public String convert(String s, int numRows) { 3 4 if (numRows == 1) return s; 5 6 StringBuilder ret = new StringBuilder(); 7 int n = s.length(); 8 int cycleLen = 2 * numRows - 2; 9 10 for (int i = 0; i < numRows; i++) { 11 for (int j = 0; j + i < n; j += cycleLen) { 12 ret.append(s.charAt(j + i)); 13 if (i != 0 && i != numRows - 1 && j + cycleLen - i < n) 14 ret.append(s.charAt(j + cycleLen - i)); 15 } 16 } 17 return ret.toString(); 18 } 19 }
LeetCode-#180 Employees Earning More Than Their Managers
在職員表中找到薪資比其經理還高的職員的名字
這幾天做過幾個數據庫的題目後終於有了點感覺, 也沒啥說的:
1 SELECT e1.Name AS Employee 2 FROM 3 Employee e1, 4 Employee e2 5 WHERE 6 e2.Id = e1.ManagerId 7 AND e1.Salary > e2.Salary 8 ;
或者也可以用join, 下面這是官方提供的答案之一:
1 SELECT 2 a.NAME AS Employee 3 FROM Employee AS a JOIN Employee AS b 4 ON a.ManagerId = b.Id 5 AND a.Salary > b.Salary 6 ;
據說用JOIN會比用WHERE快一些, 我也不太確定, 總之就聽他的好了, 以後考慮多用JOIN
LeetCode-Algorithms #006 ZigZag Conversion, Database #180 Employees Earning More Than Their Managers