第一题:
为防止丢失精度用乘法代替除法。
public class Solution {
public boolean checkStraightLine(int[][] c) {
boolean flag=true;
for(int i=2;i<c.length;i++) {
if((c[i][1]-c[i-1][1])*(c[i-1][0]-c[i-2][0])!=(c[i-1][1]-c[i-2][1])*(c[i][0]-c[i-1][0])) {
flag=false;
break;
}
}
return flag;
}
}
第二题:
字典树上dfs,将 '/' 转换为'z'+1 需要注意的是若之前已经添加完了作为当前单词前缀的单词,则需要看下一个字符是否为'/',若是则停止添加,不是则继续添加,在dfs的过程中同样需要注意这一点。
public class Solution {
public List<String> ans=new ArrayList<String>();
public List<String> removeSubfolders(String[] folder) {
Trie trie=new Trie();
for(String temp:folder) {
char[] str=temp.toCharArray();
for(int i=0;i<str.length;i++)
if(str[i]=='/')
str[i]='z'+1;
trie.insert(str);
}
dfs(trie.root.son[26],new StringBuilder());
return ans;
}
public void dfs(Trie.Node root,StringBuilder buf) {
if(root==null)
return ;
if(root.val=='z'+1)
buf.append("/");
else
buf.append(root.val);
if(root.isEnd) {
ans.add(buf.toString());
for(int i=0;i<26;i++) {
if(root.son[i]!=null)
dfs(root.son[i],buf);
}
buf.deleteCharAt(buf.length()-1);
return ;
}
for(int i=0;i<27;i++) {
if(root.son[i]!=null)
dfs(root.son[i],buf);
}
buf.deleteCharAt(buf.length()-1);
}
static class Trie{
class Node{
int num;
Node[] son;
boolean isEnd;
char val;
Node(){
this.num=1;
this.son=new Node[27];
this.isEnd=false;
}
}
Node root;
Trie(){
this.root=new Node();
}
void insert(char[] str){ //为字典添加单词
Node temp=root;
for(int i=0;i<str.length;i++) {
if(temp.son[str[i]-'a']==null) {
temp.son[str[i]-'a']=new Node();
temp.son[str[i]-'a'].val=str[i];
}
else {
temp.son[str[i]-'a'].num++;
}
temp=temp.son[str[i]-'a'];
if(temp.isEnd&&i+1<str.length&&str[i+1]=='z'+1)
return ;
}
temp.isEnd=true;
}
boolean has(String str) { //判断单词是否在字典中
if(str==""||str.length()==0)
return false;
else {
Node temp=root;
char[] res=str.toCharArray();
for(int i=0;i<res.length;i++) {
if(temp.son[res[i]-'a']==null)
return false;
else
temp=temp.son[res[i]-'a'];
}
return temp.isEnd;
}
}
int countPrefix(String pre) { //统计单词前缀
if(pre==""||pre.length()==0)
return -1;
else {
char[] str=pre.toCharArray();
Node temp=root;
for(int i=0;i<str.length;i++) {
if(temp.son[str[i]-'a']==null)
return 0;
else
temp=temp.son[str[i]-'a'];
}
return temp.num;
}
}
}
}
第三题:
滑窗+二分最短的子串的长度,需要前缀和优化一下,若当前的窗口为需替换的子串,则看剩下的Q,W,E,R的总和是否小于等于n/4。
public class Solution {
public static final int Q=0;
public static final int W=1;
public static final int E=2;
public static final int R=3;
public boolean check(int[][] pre,int len,int n) {
for(int i=1;i+len-1<=n;i++) {
int q_sum=pre[Q][i-1]+pre[Q][n]-pre[Q][i+len-1];
int w_sum=pre[W][i-1]+pre[W][n]-pre[W][i+len-1];
int e_sum=pre[E][i-1]+pre[E][n]-pre[E][i+len-1];
int r_sum=pre[R][i-1]+pre[R][n]-pre[R][i+len-1];
if(q_sum<=n/4&&w_sum<=n/4&&e_sum<=n/4&&r_sum<=n/4)
return true;
}
return false;
}
public int balancedString(String s) {
int n=s.length();
int ans=-1;
int[][] pre=new int[4][s.length()+1];
int l=0;
int r=n;
s=" "+s;
for(int i=1;i<=n;i++) {
pre[Q][i]=pre[Q][i-1]+(s.charAt(i)=='Q'?1:0);
pre[W][i]=pre[W][i-1]+(s.charAt(i)=='W'?1:0);
pre[E][i]=pre[E][i-1]+(s.charAt(i)=='E'?1:0);
pre[R][i]=pre[R][i-1]+(s.charAt(i)=='R'?1:0);
}
while(l<=r) {
int mid=(l+r)>>1;
if(check(pre,mid,n)) {
ans=mid;
r=mid-1;
}
else
l=mid+1;
}
return ans;
}
}
第四题:
线段树+离散化+贪心
首先以endTime由小到大进行排序,线段树维护区间最大值,转移的时候查询[1,startTime]这段区间的最大值进行转移,并将endTime的最大值进行更新。
public class Solution {
public int jobScheduling(int[] startTime, int[] endTime, int[] profit) {
int n=startTime.length;
TreeSet<Integer> set=new TreeSet<Integer>();
ArrayList<Node> cur=new ArrayList<Node>();
for(int i=0;i<n;i++) {
set.add(startTime[i]);
set.add(endTime[i]);
cur.add(new Node(startTime[i],endTime[i],profit[i]));
}
Collections.sort(cur);
SegTree sgt=new SegTree(set.size());
sgt.build(1, 1, set.size());
ArrayList<Integer> buf=new ArrayList<Integer>();
buf.addAll(set);
for(int i=0;i<n;i++) {
int index=Collections.binarySearch(buf, cur.get(i).begin)+1;
int all=sgt.ask(1, 1, index)+cur.get(i).p;
sgt.change(1, Collections.binarySearch(buf, cur.get(i).end)+1, all);
}
return sgt.ask(1, 1, buf.size());
}
static class Node implements Comparable<Node>{
int begin;
int end;
int p;
public Node(int begin,int end,int p) {
this.begin=begin;
this.end=end;
this.p=p;
}
@Override
public int compareTo(Node o) {
return this.end-o.end;
}
}
static class SegTree{
class Node{
int l;
int r;
int val;
public Node(int l,int r) {
this.l=l;
this.r=r;
}
}
public Node[] t;
public SegTree(int n) {
this.t=new Node[(n+10)<<2];
}
public void pushUp(int p) {
t[p].val=Math.max(t[p*2].val, t[p*2+1].val);
}
public void build(int p,int l,int r) {
t[p]=new Node(l,r);
if(l==r) {
return ;
}
int mid=(l+r)>>1;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
pushUp(p);
}
public void change(int p,int index,int val) {
if(t[p].l==t[p].r) {
t[p].val=Math.max(t[p].val,val);
return ;
}
int mid=(t[p].l+t[p].r)>>1;
if(index<=mid)
change(p*2,index,val);
else
change(p*2+1,index,val);
pushUp(p);
}
public int ask(int p,int l,int r) {
if(t[p].l>=l&&t[p].r<=r)
return t[p].val;
int mid=(t[p].l+t[p].r)>>1;
int res=0;
if(l<=mid)
res=Math.max(res, ask(p*2,l,r));
if(r>mid)
res=Math.max(res, ask(p*2+1,l,r));
return res;
}
}
}