842. 将数组拆分成斐波那契序列
给定一个数字字符串 S,比如 S = "123456579",我们可以将它分成斐波那契式的序列 [123, 456, 579]。
形式上,斐波那契式序列是一个非负整数列表 F,且满足:
0 <= F[i] <= 2^31 - 1,(也就是说,每个整数都符合 32 位有符号整数类型);
F.length >= 3;
对于所有的0 <= i < F.length - 2,都有 F[i] + F[i+1] = F[i+2] 成立。
另外,请注意,将字符串拆分成小块时,每个块的数字一定不要以零开头,除非这个块是数字 0 本身。
返回从 S 拆分出来的所有斐波那契式的序列块,如果不能拆分则返回 []。
示例 1:
输入:"123456579"
输出:[123,456,579]
示例 2:
输入: "11235813"
输出: [1,1,2,3,5,8,13]
示例 3:
输入: "112358130"
输出: []
解释: 这项任务无法完成。
示例 4:
输入:"0123"
输出:[]
解释:每个块的数字不能以零开头,因此 "01","2","3" 不是有效答案。
示例 5:
输入: "1101111"
输出: [110, 1, 111]
解释: 输出 [11,0,11,11] 也同样被接受。
提示:
1 <= S.length <= 200
字符串 S 中只含有数字。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/split-array-into-fibonacci-sequence
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
代码有点儿烂,做了好久,超过人数才5点几,真TM fuck。
下面代码耗时87ms
1 public class Solution { 2 private String s; 3 private int len = -1; 4 private List<Integer> res; 5 private int e1; 6 private int e2; 7 private int e3; 8 9 private String isContinue(int m,int n,int o){ 10 String r = null; 11 String a = s.substring(m, n); 12 String b = s.substring(n, o); 13 if (a.length() > 10 || b.length() > 10) 14 return ""; 15 long a0 = Long.parseLong(a); 16 long b0 = Long.parseLong(b); 17 if (a0 > 2147483647 || b0 > 2147483647) 18 return ""; 19 e1 = (int)a0; 20 e2 = (int)b0; 21 if (a0+b0 > 2147483647) 22 return ""; 23 e3 = (int)(a0+b0); 24 String c = String.valueOf(a0 + b0); 25 if (a.charAt(0)=='0' && a.length()!=1 || b.charAt(0)=='0' && b.length() != 1) 26 r = ""; 27 else if (c.length() > len-o) 28 r = ""; 29 else if (!s.substring(o,o+c.length()).equals(c)) 30 r = ""; 31 return (r != null) ? "" : c; 32 } 33 34 private boolean helper(int m, int n, int o){ 35 if (isContinue(m,n,o).equals("")){ 36 return false; 37 } 38 39 for (int i = n; i < len; i++) { 40 for (int j = i+1; j < len; j++) { 41 String c = isContinue(m, i, j); 42 if (c.equals("")) 43 continue; 44 if (s.substring(j,j+c.length()).equals(c)){ 45 if (c.length() > len-j) 46 return false; 47 48 res.add(e1); 49 50 if (c.length() == len-j) { 51 if (e2 == e1 || res.get(res.size()-1) != e2) 52 res.add(e2); 53 res.add(e3); 54 return true; 55 } 56 if (helper(i, j, j+c.length())) 57 return true; 58 59 res.remove(res.size()-1); 60 } 61 } 62 } 63 return false; 64 } 65 public List<Integer> splitIntoFibonacci(String S) { 66 s = S; 67 len = s.length(); 68 res = new ArrayList<>(); 69 70 for (int i = 1; i < len; i++) { 71 for (int j = i+1; j < len; j++) { 72 if (helper(0,i,j)) 73 return res; 74 } 75 } 76 return res; 77 } 78 79 public static void main(String[] args) { 80 List<Integer> integers = new Solution().splitIntoFibonacci("3611537383985343591834441270352104793375145479938855071433500231900737525076071514982402115895535257195564161509167334647108949738176284385285234123461518508746752631120827113919550237703163294909"); 81 System.out.println("integers = " + integers); 82 } 83 }
下面代码耗时336ms。越改越差劲。。。至少提供了另一种解法。。。
1 public class Solution { 2 private String s; 3 private List<String> res = null; 4 private int len = -1; 5 private String last1,last2,next; 6 7 private boolean ok(String str){ 8 if (str.length() > 10 || Long.parseLong(str) > Integer.MAX_VALUE) 9 return false; 10 return true; 11 } 12 13 private boolean helper(int begin, int end){ 14 if (res.size() >= 2){ 15 last1 = res.get(res.size()-2); 16 last2 = res.get(res.size()-1); 17 next = s.substring(begin, end); 18 19 if (!ok(last1) || !ok(last2) || !ok(next) || !ok(String.valueOf(Integer.parseInt(last1)+ Integer.parseInt(last2)))) 20 return false; 21 if (Integer.parseInt(last1) + Integer.parseInt(last2) == Integer.parseInt(next)) { 22 if (next.charAt(0)=='0'&&next.length()>1) 23 return false; 24 res.add(next); 25 } else { 26 return false; 27 } 28 if (end == len) 29 return true; 30 } else { 31 String last = s.substring(begin, end); 32 if (last.charAt(0)=='0' && last.length()>1) 33 return false; 34 res.add(last); 35 } 36 // end不是合适的划分位置 37 for (int i = 1; i < len;++i) { 38 if (end+i > len) 39 break; 40 if (helper(end, end+i)) 41 return true; 42 } 43 res.remove(res.size()-1); 44 return false; 45 } 46 47 public List<Integer> splitIntoFibonacci(String S) { 48 s = S; 49 res = new ArrayList<>(); 50 len = s.length(); 51 for (int i = 1; i < len; i++) { 52 if (helper(0,i)) 53 break; 54 } 55 List<Integer> r = new ArrayList<>(); 56 for (String s : res) { 57 r.add(Integer.parseInt(s)); 58 } 59 return r; 60 } 61 62 63 public static void main(String[] args) { 64 List<Integer> integers = new Solution().splitIntoFibonacci("112358130"); 65 System.out.println("integers = " + integers); 66 } 67 }
终于找到原因了,string.substring()是一个很耗时的操作,把每一个字符串转化整数后,存储起来供后续使用,能极大提高效率。。。下面代码大约15-35ms之间。
1 public class Solution { 2 private String s; 3 private List<Integer> res = null; 4 private int len = -1; 5 private int last1,last2; 6 private String next; 7 private long[][] memory = null; 8 9 private boolean helper(int begin, int end){ 10 if (res.size() >= 2){ 11 last1 = res.get(res.size()-2); 12 last2 = res.get(res.size()-1); 13 next = s.substring(begin, end); 14 if (next.length() <= 10 && memory[begin][end] == 0) 15 memory[begin][end] = Long.parseLong(next); 16 if (next.charAt(0)=='0'&&next.length()>1 || next.length() > 10 || memory[begin][end] > Integer.MAX_VALUE) 17 return false; 18 19 if (last1 + last2 == memory[begin][end]) { // memory[begin][end]存储的就是next 20 res.add((int)memory[begin][end]); 21 } else { 22 return false; 23 } 24 if (end == len) 25 return true; 26 } else { 27 if (memory[begin][end] == 0) { 28 String last = s.substring(begin, end); 29 if (last.length() > 10 || memory[begin][end] > Integer.MAX_VALUE) 30 return false; 31 memory[begin][end] = Long.parseLong(last); 32 if (last.charAt(0)=='0' && last.length()>1) 33 return false; 34 } 35 res.add((int)memory[begin][end]); 36 } 37 // end不是合适的划分位置 38 for (int i = 1; i < len;++i) { 39 if (end+i > len) 40 break; 41 42 if (helper(end, end+i)) 43 return true; 44 } 45 res.remove(res.size()-1); 46 return false; 47 } 48 49 public List<Integer> splitIntoFibonacci(String S) { 50 s = S; 51 res = new ArrayList<>(); 52 len = s.length(); 53 memory = new long[len+1][len+1]; 54 for (int i = 1; i < len; i++) { 55 if (helper(0,i)) 56 break; 57 } 58 return res; 59 } 60 61 public static void main(String[] args) { 62 List<Integer> integers = new Solution().splitIntoFibonacci("214748364721474836422147483641"); 63 System.out.println("integers = " + integers); 64 } 65 }