最近的请求次数
题目:写一个 RecentCounter 类来计算最近的请求。它只有一个方法:ping(int t),其中 t 代表以毫秒为单位的某个时间。返回从 3000 毫秒前到现在的 ping 数。任何处于 [t - 3000, t] 时间范围之内的 ping 都将会被计算在内,包括当前(指 t 时刻)的 ping。保证每次对 ping 的调用都使用比之前更大的 t 值。
思路:完美的遵循了越是简单的题目描述越不说人话的特点,憋了半个多小时又在群里咨询才算明白题意了:就是当前数字3000以内(包括三千)的次数。比如第一个1,前面没有,只有这一个,所以就是1.再之后第二个100,前面的1在3000以内,所以算1次,也就是一共两次。再之后第三个3001,3001-1=3000.属于范围内的,所以一共是1,100 ,3001三次。最后的3002.这个时候1已经超过3000了所以不算, 100,3001,3002一共三次,over
只要明白题意做是很容易做出来的,就是性能问题。我先去实现了。目前打算用数组。
思路没问题,数组没问题,性能问题大了,,只超过了百分之十四的人。。。先贴代码:
class RecentCounter {
private int[] num;
int i;
public RecentCounter() {
num = new int[10000];
}
public int ping(int t) {
num[i] = t;
i++;
int res = 0;
for(int n = i-1; n>=0;n-- ){
if(t-num[n]<=3000){
res++;
}else{
break;
}
}
return res;
}
}
/**
* Your RecentCounter object will be instantiated and called as such:
* RecentCounter obj = new RecentCounter();
* int param_1 = obj.ping(t);
*/
其实还能实现的方式有很多,比如list也ok,但是我以为数组性能会最好,,,谁知道会这样。我直接去看排行第一的代码吧:
class RecentCounter {
int[] a = new int[10000];
int i = 0;
int l = 0;
int length = 0;
public RecentCounter() {
}
public int ping(int t) {
a[i] = t;
i++;
length++;
while (l < i) {
if (a[l] < t - 3000) {
l++;
length--;
} else
break;
}
return length;
}
}
很奇怪啊,差不多的思路,我到现在也不懂为啥人家第一,我差不多倒数第一。不就是我从后往前遍历,他从前往后遍历么?算了算了,不求甚解。这道题其实比较简单,直接下一题吧。
重新排列日志文件
题目:你有一个日志数组 logs。每条日志都是以空格分隔的字串。对于每条日志,其第一个字为字母数字标识符。然后,要么:标识符后面的每个字将仅由小写字母组成,或;标识符后面的每个字将仅由数字组成。我们将这两种日志分别称为字母日志和数字日志。保证每个日志在其标识符后面至少有一个字。将日志重新排序,使得所有字母日志都排在数字日志之前。字母日志按内容字母顺序排序,忽略标识符;在内容相同时,按标识符排序。数字日志应该按原来的顺序排列。返回日志的最终顺序。
思路:这道题也很眼熟啊,跟之前的奇偶数排列数组不是差不多么?之不过这个题更加麻烦,因为在数字和字母的基础上还要按照字母顺序排序(这点应该是最麻烦的)。但是麻烦和困难完全不一样。这道题仅仅是处理上的麻烦,而不是做不出来的困难,我去一点点实现啦
class Solution {
public String[] reorderLogFiles(String[] logs) {
if(logs.length<=1)return logs;
List<String> num=new LinkedList();
List<String> alph=new ArrayList();
for(String tmp:logs){
for(int i=0;i<tmp.length();i++){
if(tmp.charAt(i)==' '){
if(tmp.charAt(i+1)>='0'&&tmp.charAt(i+1)<='9')
num.add(tmp);
else
alph.add(tmp);
break;
}
}
}
Collections.sort(alph,new Comparator<String>(){
public int compare(String t1,String t2){
int i=1,j=1;
for(;i<t1.length();i++)
if(t1.charAt(i-1)==' ')
break;
for(;j<t2.length();j++)
if(t2.charAt(j-1)==' ')
break;
int t=(t1.substring(i)).compareTo(t2.substring(j));
if(t==0) return (t1.substring(0,i-1).compareTo(t2.substring(0,j-1)));
return t;
}
});
String res[]=new String[logs.length];
int i=0;
for(String str:alph)
res[i++]=str;
for(String str:num)
res[i++]=str;
return res;
}
}
如上图,那么长的一大块。简单来讲思路很简单,就是先分出数字还是字母。这里本身list是有序的,能保证数字的顺序,剩下的就是字母的排序问题,重写了sort方法,每一步都中规中矩,没亮点但是很稳的过了。性能也超过百分之八十多的人。虽然没及格但是因为真的这道题让我除了重写sort看不出考点,所以就这样吧。下一题。
二叉树的范围和
题目:给定二叉搜索树的根结点 root,返回 L 和 R(含)之间的所有结点的值的和。二叉搜索树保证具有唯一的值。
思路:看了半天题目,还是画了图才懂是什么意思。其实比想的简单,就是给定左右两个节点值。找到所有在这两个值之间(包含左右节点值)数值的和。最无脑的办法就是遍历,值处于这个数值之间的就相加,不然不加。但是其实这么做是很傻的。因为这是一个二叉搜索树。严格遵守左小右大。所以其实是可以有规律的。比如当前节点已经大于给定R了,只要再遍历当前节点的left树就行了,右数只会越来越大,没必要遍历。同理当前节点值小于L,则只要遍历当前节点的right树,左数只会越来越小。接下来我去实现了
class Solution {
int sum;
public int rangeSumBST(TreeNode root, int L, int R) {
addNode(root,L,R);
return sum;
}
public void addNode( TreeNode root,int L,int R){
if(root==null) return;
if(root.val>=L && root.val<=R){
sum += root.val;
addNode(root.right,L,R);
addNode(root.left,L,R);
}
if(root.val<L) addNode(root.right,L,R);
if(root.val>R) addNode(root.left,L,R);
}
}
一次通过性能超过百分百,所以不再看题解什么的了。直接下一题。
有效的山脉数组
题目:给定一个整数数组 A,如果它是有效的山脉数组就返回 true,否则返回 false。让我们回顾一下,如果 A 满足下述条件,那么它是一个山脉数组:
A.length >= 3
在 0 < i < A.length - 1 条件下,存在 i 使得:
A[0] < A[1] < ... A[i-1] < A[i]
A[i] > A[i+1] > ... > A[B.length - 1]
思路:这道题我之前怎么看怎么眼熟,结果去找了之前的笔记,发现在第41篇中山脉数组的封顶索引,跟这道题类似,或者说这道题是那道题的爸爸。那道题是在这基础上的操作,这个是基础。话题转回来来说思路。首先判断第一个和最后一个要小于最大值,其次最大值前面的小于等于最大值,最大值后面的小于等于最大值,over。我去写代码了
这道题实现很简单,直接贴代码:
class Solution {
public boolean validMountainArray(int[] A) {
if(A.length==0) return false;
int max = 0;
int index = -1;
for(int i = 0;i<A.length;i++){
if(A[i]>max){
max = A[i];
index = i;
}
}
if(A[0]==max || A[A.length-1]==max) return false;
int i = 0;
while(i<index){
if(A[i]>=A[i+1]) return false;
i++;
}
while(i<A.length-1){
if(A[i]<=A[i+1]) return false;
i++;
}
return true;
}
}
但是想要性能好就有点难了。我这个反正才超过六十多的人。我直接去看看性能第一的代码吧:
class Solution {
public boolean validMountainArray(int[] A) {
//linera search
int i = 0;
//start walk upward
while(i < A.length - 1 && A[i] < A[i+1]) i++;
//peak cannot be 1st and last
if (i == 0 || i == A.length - 1) return false;
//start walk down
while (i + 1 < A.length && A[i] > A[i+1]) i++;
return i == A.length - 1;
}
}
然后今天的笔记就记到这里了,如果稍微帮到你了记得点个喜欢点个关注。明天周一,