算法过程:
1.每个字符串的输出,需要经历的步骤是:
a.检查undo list 更新 buff;
b.填写buff,并更新undo list;
c.回车;
2.关键是步骤a,既要考虑从undo list中选出来的前缀A,也要考虑buff中现有的B;
3.通常情况,直接用A替换B。特殊情况:
1) B和A相同,则不需要替换;
2) B是A的前缀,并且B.length+2>A.length,不需要替换。
4.时间复杂度:O(n^2)
菜鸟的代码:
import java.util.*; import java.util.regex.*; import java.text.*; import java.math.*; public class UndoHistory { public int minPresses(String[] lines) { List<String> undo = new ArrayList(); int i,j,k,max,count; String temp,m,buff; buff = ""; undo.add(""); count = 0; for(i=0;i<lines.length;i++){ //find the longest substr in undo Iterator<String> it = undo.iterator(); m=""; while(it.hasNext()){ temp = it.next(); if(temp.length()>m.length()&&temp.length()<=lines[i].length()){ if(temp.equals(lines[i].substring(0,temp.length()))){ m = temp; } } } //update the buff //System.out.println("buff="+buff+"m="+m+"count="+count); if(!m.equals(buff)){ //count the mouse click if(buff.length()<=lines[i].length()&&buff.equals(lines[i].substring(0,buff.length()))&&m.length()<=buff.length()+2){ //这个情况很特殊,很容易漏掉 } else{ count+=2; buff=new String(m); } } //System.out.println("char:"+count); //if the longset undo equals buffer,then no mouse clicks
j=buff.length();
for(;j<lines[i].length();j++){ buff+=lines[i].charAt(j); undo.add(new String(buff)); //count the char count++; } //System.out.println("enter:"+count); //count the enter count++; } return count; } } //Powered by KawigiEdit 2.1.4 (beta) modified by pivanof!
大神的代码java:
import java.util.*; import java.util.regex.*; import java.text.*; import java.math.*; public class UndoHistory { public int minPresses(String[] lines) { HashSet<String> prefixes = new HashSet<String>(); int ans = 0; String prev = ""; for (String s : lines) { int cur = s.length() + 3; if (s.startsWith(prev)) { cur = s.length() - prev.length() + 1; } for (int i = 1; i <= s.length(); ++i) { if (prefixes.contains(s.substring(0, i))) { cur = Math.min(cur, s.length() - i + 3); } prefixes.add(s.substring(0, i)); } prev = s; ans += cur; } return ans; } }
大神的代码c++:
#include <vector> #include <list> #include <map> #include <set> #include <deque> #include <stack> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <ctime> #include <string> #include <cstring> using namespace std; class UndoHistory { public: int minPresses(vector <string>); }; int UndoHistory::minPresses(vector <string> lines) { int c=lines[0].length()+1; int len,max,ind,last=0; int x=lines.size(); int ar[x]; for (int i=0;i<x;i++) { ar[i]=lines[i].length(); } for (int i=1;i<x;i++) { max=-1,ind=-1; for (int j=i-1;j>=0;j--) { len=0; for (int k=0;k<min(ar[j],ar[i]);k++) { if (lines[j][k]!=lines[i][k]) break; else len++; } if (j == i-1) last=len; if (len > max) { max=len; ind=j; } } if (ind == i-1 && max==ar[i-1]) ; else if (max == last+1 && last==ar[i-1]) { max--; } else c+=2; if (max > 0) { len=ar[i] - max; } else { len=ar[i]; } c+=len+1; } return c; } //Powered by [KawigiEdit] 2.0!
分析:
算法:Greedy, Simple Search, Iteration
对比:
1.Java大神的思考方式比我牛。
我是先到undo list里把前缀找出来,然后再拿前缀和buff当前值做比较,决定要不要替换。
大神用优化的思维来看待这个问题,首先考虑只采用buff的情况,然后再遍历undo list,看通过history能不能有优化。
2.Java大神的HashSet用得帅气,学习了。
3.C++大神的代码可读性捉急。。。
4.C++大神的想法和我的比较接近。但是他没有真实地用一个undo list。而是每次都那当前字符串和以前的字符串求一个最长前缀。这样做的确可以节省不少存储空间,但是略显麻烦。。。
总结:
1.java大神的代码的确体现出了greedy算法思想。少去了很多细节上的判断处理。
2.菜鸟表示要好好去学习一下HashSet。