[LeetCode] 第159场周赛题解

第一题:

为防止丢失精度用乘法代替除法。

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;
    	}
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值