LeetCode--日常刷题

日常刷题,以easy和medium为主练练手
985. Sum of Even Numbers After Queries
每次查询只需要O(1)的时间复杂度

class Solution {
    public int[] sumEvenAfterQueries(int[] A, int[][] queries) {
        int oddSum=0,evenSum=0;
        for(int i=0;i<A.length;i++){
            if((A[i] & 1)==1)
                oddSum+=A[i];
            else
                evenSum+=A[i];
        }
        int[] ans=new int[queries.length];
        for(int i=0;i<ans.length;i++){
            //A[queries[i][1]]为偶数  queries[i][0]为偶数
            if((A[queries[i][1]] & 1)==0){
                if((queries[i][0] & 1)==0)
                {
                    evenSum+=queries[i][0];
                    ans[i]=evenSum;
                    A[queries[i][1]]+=queries[i][0];
                }
                else   //A[queries[i][1]]为偶数  queries[i][0]为奇数
                {
                    evenSum-=A[queries[i][1]];
                    ans[i]=evenSum;
                    oddSum+=queries[i][0]+A[queries[i][1]];
                    A[queries[i][1]]+=queries[i][0];
                }
            }
            else{
                //A[queries[i][1]]为奇数,queries[i][0]为偶数
                if((queries[i][0] & 1)==0){
                    oddSum+=queries[i][0];
                    A[queries[i][1]]+=queries[i][0];
                    ans[i]=evenSum;
                }
                else  //A[queries[i][1]]为奇数,queries[i][0]为奇数
                {
                    evenSum+=A[queries[i][1]]+queries[i][0];
                    oddSum-=A[queries[i][1]];
                    ans[i]=evenSum;
                    A[queries[i][1]]+=queries[i][0];
                }
            }
        }
        return ans;
    }
}

365. Water and Jug Problem

class Solution {
    public boolean canMeasureWater(int x, int y, int z) {
        if(z==0 || z==x || z==y || x+y==z)
            return true;
        if(x+y<z)
            return false;
        int GCD=gcd(x,y);
        return GCD==0?false:z%GCD==0;
        
    }
    
    int gcd(int x,int y){
        return y==0?x:gcd(y,x%y);
    }
}

399. Evaluate Division
一个图论可达性搜索的问题

class Solution {
    
    public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {
        int n_points = 0;
        HashMap<String, Integer> map = new HashMap<>();
        for (List<String> list : equations) {
            for (String s : list) {
                if (!map.containsKey(s)) {
                    map.put(s, n_points++);
                }
            }
        }
        double[][] adj = new double[n_points][n_points];
        for (int i = 0; i < equations.size(); i++) {

            String start = equations.get(i).get(0);
            int startIndex = map.get(start);
            String end = equations.get(i).get(1);
            int endIndex = map.get(end);
            adj[startIndex][endIndex] = values[i];
            if (values[i] != 0.0)
                adj[endIndex][startIndex] = 1 / values[i];
        }
        double[] ans = new double[queries.size()];
        Arrays.fill(ans, -1.0);

        for (int i = 0; i < ans.length; i++) {
            String a = queries.get(i).get(0);
            String b = queries.get(i).get(1);
            if (!map.containsKey(a) || !map.containsKey(b))
                ans[i] = -1.0;
            else if(a.equals(b)){
                ans[i]=1.0;
            }
            else {
                
                int start = map.get(a), end = map.get(b);
                System.out.println(start+end);
                Queue<double[]> que = new LinkedList<>();
                boolean[] visited = new boolean[n_points + 1];
                for (int k = 0; k < n_points; k++) {
                    if (adj[start][k] != 0.0) {
                        visited[k] = true;
                        System.out.print(k);
                        double[] tmp = {(double) k, adj[start][k]};
                        que.add(tmp);
                    }
                }
                
                while (!que.isEmpty()) {
                    double[] tmp = que.poll();
                    int source = (int) tmp[0];
                    if (source == end) {
                        ans[i] = tmp[1];
                        System.out.println("haha");
                        break;
                    }
                    for (int j = 0; j < n_points; j++) {
                        if (!visited[j] && adj[source][j] != 0.0) {
                            double[] temp = {(double) j, adj[source][j] * tmp[1]};
                            System.out.println("xixi"+adj[source][j] * tmp[1]);
                            que.add(temp);
                            visited[j] = true;
                        }
                    }
                }
            }
        }
        return ans;
    }
}

443. String Compression
双指针算法,原地

class Solution {
    public int compress(char[] chars) {
        int i=0,j=0;
        while(j<chars.length){
            int idx=j;
            char c=chars[idx];
            int count=1;
            while(idx+1<chars.length && chars[idx+1]==c){
                count++;
                idx++;
            }
                
            if(count==1)
            {
                chars[i++]=chars[j];
            }
            else{
                chars[i++]=chars[j];
                String str=String.valueOf(count);
                for(int n=0;n<str.length();n++)
                    chars[i++]=str.charAt(n);
            }
            j=idx+1;
        }
        return i;
    }
}

404. Sum of Left Leaves

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int sumOfLeftLeaves(TreeNode root) {
        return dfs(root, null);
    }
    
    private int dfs(TreeNode root, TreeNode parent) {
        if (root == null) return 0;
        if (root.left == null && root.right == null && parent != null && parent.left == root) {
            return root.val;
        }
        return dfs(root.left, root) + dfs(root.right, root); 
    }
}

344. Reverse String

class Solution {
    public void reverseString(char[] s) {
        int i=0,j=s.length-1;
        while(i<j){
            char tmp=s[i];
            s[i++]=s[j];
            s[j--]=tmp;
        }
    }
}

345. Reverse Vowels of a String

class Solution {
    public String reverseVowels(String s) {
        char[] sb=s.toCharArray();
        int i=0,j=s.length()-1;
        while(i<j){
            while(i<j && check(sb[i]))
                  i++;
                  
            while(i<j && check(sb[j]))
                  j--;
            if(i>=j)
                  break;
            else{
                char tmp=sb[i];
                sb[i++]=sb[j];
                sb[j--]=tmp;
            }
        }
        return new String(sb); 
    }
                  
    public boolean check(char c){
        return c!='a' && c!='e' && c!='i' && c!='o' && c!='u' && c!='A' && c!='E' && c!='I' && c!='O' && c!='U';
    }
}

1074. Number of Submatrices That Sum to Target
比较容易想到的是二维前缀和方法,先用平方复杂度求二维前缀和,但是后面的矩形枚举暴力解法,大概是O(m^4),过不了最后两个测试数据,因此需要优化。不能AC,算法如下:

class Solution {
    public int numSubmatrixSumTarget(int[][] matrix, int target) {
        
        int m=matrix.length,n=matrix[0].length,ans=0;
        int[][] preSum=new int[m+1][n+1];
        for(int i=1;i<=m;i++){
            for(int j=1;j<=n;j++)
            {
                preSum[i][j]=preSum[i-1][j]+preSum[i][j-1]-preSum[i-1][j-1]+matrix[i-1][j-1];
                System.out.print(preSum[i][j]+" ");
            }
            System.out.println();   
        }
        
        int count=m*n;
        for(int i=1;i<=count;i++){
            for(int j=i;j<=count;j++){
                int x1=(i-1)/n+1,y1=(i-1)%n+1,x2=(j-1)/n+1,y2=(j-1)%n+1;
                if(x2<x1 || y2<y1)
                    continue;

                int tmp=preSum[x2][y2]-preSum[x2][y1-1]-preSum[x1-1][y2]+preSum[x1-1][y1-1];
                if(tmp==target)
                {
                    ans++;
                }
                    
            }
        }
            return ans;
    }
}

再讨论区学习了一下,有一种O(m^3)的算法如下:
先求出每排数据的前缀和,前缀和一维的,算法复杂度为O(N^2)。对于处在不同的列

class Solution {
    public int numSubmatrixSumTarget(int[][] m, int t) {
        for(int[] r : m) {
            int sum = 0;
            for(int i = 0; i < r.length; i++) {
                sum += r[i];
                r[i] = sum;
            }
        }
        
        int res = 0;
        for(int c1 = 0; c1 < m[0].length; c1++) {
            for(int c2 = c1; c2 < m[0].length; c2++) {
                Map<Integer, Integer> map = new HashMap<>();
                map.put(0, 1);
                int preSum = 0;
                for(int r = 0; r < m.length; r++) {
                    int cur = m[r][c2] - (c1 > 0 ? m[r][c1-1] : 0);
                    preSum += cur;
                    res += map.getOrDefault(preSum - t, 0);
                    map.put(preSum, map.getOrDefault(preSum, 0) + 1);
                }
            }
        }
        return res;
    }
}

1051. Height Checker
直接对原数组进行排序,然后检查位置就行

class Solution {
    public int heightChecker(int[] heights) {
    
        int[] sorted=heights.clone();
        Arrays.sort(sorted);
        
        int ans=0;
        for(int i=0;i<heights.length;i++)
        {
            if(sorted[i]!=heights[i])
                ans++;
        }
        return ans;
    }
}

1052. Grumpy Bookstore Owner
定长滑动窗口问题,只要求出固定长度窗口内不满意的客户转为满意的最大值,然后要总客户数量减去原始不满意的人数,最后加上转变的人数。

class Solution {
    public int maxSatisfied(int[] customers, int[] grumpy, int X) {
        int total=0,unsatisfyTotal=0;
        for(int i=0;i<customers.length;i++)
        {
            total+=customers[i];
            unsatisfyTotal+=grumpy[i]*customers[i];
        }
        int convert=0,maxConvert=0;
        for(int i=0;i<customers.length;i++){
            convert+=grumpy[i]*customers[i];
            if(i>=X)
                convert-=grumpy[i-X]*customers[i-X];
            maxConvert=Math.max(maxConvert,convert);
        }
        return total-unsatisfyTotal+maxConvert;
    }
}

1053. Previous Permutation With One Swap
这个问题与Next Element III有点像,算法思路一致。

class Solution {
    public int[] prevPermOpt1(int[] A) {
        int j=A.length-1;
        for(;j-1>=0;j--){
            if(A[j-1]>A[j])
                break;
        }
        if(j==0)
            return A;
        int q=j-1,delta=Integer.MAX_VALUE,index=j;
        for(;j<A.length;j++){
            if(A[q]-A[j]>0 && A[q]-A[j]<delta)
            {
                delta=A[q]-A[j];
                index=j;
            }
        }
        int tmp=A[index];
        A[index]=A[q];
        A[q]=tmp;
        return A;
    }
}

1054. Distant Barcodes

class Solution {
    public int[] rearrangeBarcodes(int[] barcodes) {
        
        HashMap<Integer,Integer> counter=new HashMap<>();
        int maxCount=Integer.MIN_VALUE,val=barcodes[0];
        for(int i:barcodes){
            int fre=counter.containsKey(i)?counter.get(i):0;
            counter.put(i,fre+1);
            if(fre+1>maxCount){
                maxCount=fre+1;
                val=i;
            }
        }
        int[] ans=new int[barcodes.length];
        int i=0;
        while(maxCount>0){
            ans[i]=val;
            maxCount--;
            i+=2;
        }
        counter.remove(val);
        for(int key:counter.keySet()){
            int count=counter.get(key);
            while(count>0){
                i=i>=barcodes.length?1:i;
                ans[i]=key;
                count--;
                i+=2;
                
            }
        }
        return ans;
    }
}

1022. Sum of Root To Leaf Binary Numbers
基础的树深度优先搜索算法,注意这里的位运算需要加括号,因为位运算的优先级要低于加减法运算

class Solution {
    
    public static int ans;
    
    public int sumRootToLeaf(TreeNode root) {
        ans=0;
        recursive(root,0);
        return ans;
    }
    
    
    public static void recursive(TreeNode node,int val)
    {
        if(node.left==null && node.right==null)
        {
            ans+=(val<<1)+node.val;
            return;
        }
        
        int newVal=(val<<1)+node.val;
        if(node.left!=null){
            recursive(node.left,newVal);
        }
        if(node.right!=null){
            recursive(node.right,newVal);
        }
    }
}

1025. Divisor Game

class Solution {
    public boolean divisorGame(int N) {
        return (N & 1)==0;
    }
}

1026. Maximum Difference Between Node and Ancestor

class Solution {
    
    public int maxAncestorDiff(TreeNode root) {
        
        return recursive(root,Integer.MAX_VALUE,Integer.MIN_VALUE);
    }  
    public static int recursive(TreeNode node,int minVal,int maxVal){
        
        if(node==null)
            return 0;
        minVal=Math.min(minVal,node.val);
        maxVal=Math.max(maxVal,node.val);
        if(node.left==null && node.right==null)
            return Math.abs(maxVal-minVal);
        return Math.max(recursive(node.left,minVal,maxVal),recursive(node.right,minVal,maxVal));
        
    }
}

1023. Camelcase Matching
驼峰命名匹配这个问题描述有点脏,给的样例不全。比如"Ccoo"和"Ccbobo"也是匹配的。以小写字母开头的字符串也是合法的。

class Solution {
    public static List<Boolean> camelMatch(String[] queries, String pattern) {

        List<Boolean> ans = new LinkedList<>();
        List<String> target = partition(pattern);

        for (int i = 0; i < queries.length; i++) {

            List<String> source = partition(queries[i]);
            if (source.size() != target.size()) {
                ans.add(false);
                continue;
            }
            int j = 0;
            for (; j < source.size(); j++) {
                String ps = target.get(j), ss = source.get(j);
                if (!isValid(ps, ss)) {
                    ans.add(false);
                    break;
                }
            }
            if (j == source.size())
                ans.add(true);
        }
        return ans;
    }
   //字符串的一节与模式串的一节是否匹配
    public static boolean isValid(String target, String source) {  //target:模式字符串
        for (int i = 0, j = 0; i < target.length(); i++) {
            while (j < source.length() && target.charAt(i) != source.charAt(j))
                j++;
            if (j == source.length())
                return false;
            else
                j++;
        }
        return true;
    }
      //字符串拆分
    public static List<String> partition(String s) {
        int i = 0;
        while(i<s.length() && s.charAt(i)>='a' && s.charAt(i)<='z')
            i++;
        List<String> ans = new ArrayList<>();
        while (i < s.length()) {
            int j = i;
            while (j + 1 < s.length() && s.charAt(j + 1) >= 'a' && s.charAt(j + 1) <= 'z')
                j++;

            ans.add(s.substring(i, j + 1));
            i = j + 1;
        }
        for (int n = 0; n < ans.size(); n++)
            System.out.println(ans.get(n));
        return ans;
    }
}

1037. Valid Boomerang
当三点不共线时,即为true。边界条件的判断有些脏。第一行的排序实际上不需要,不过使用lambda表达式替代比较器代码简洁不少。

class Solution {
    public boolean isBoomerang(int[][] points) {
        Arrays.sort(points,(a,b)->a[0]-b[0]==0?a[1]-b[1]:a[0]-b[0]);
        if(points[0][0]==points[1][0] && points[1][0]==points[2][0])
            return false;
        if((points[0][0]==points[1][0] && points[0][1]==points[1][1]) || (points[1][0]==points[2][0] && points[1][1]==points[2][1]) )
            return false;
        if(points[1][0]-points[0][0]==0 || points[2][0]-points[0][0]==0)
            return true;
        double k1=(double)(points[1][1]-points[0][1])/(points[1][0]-points[0][0]);
        double k2=(double)(points[2][1]-points[0][1])/(points[2][0]-points[0][0]);
        return k1!=k2;
    }
}

1034. Coloring A Border
对于连通分量采用BFS进行搜索,再判断是否为边缘元素,代码有点冗长,时间复杂度较高,但是空间复杂度特别好。

class Solution {
    
    class Coordinate{
        int x;
        int y;
        public Coordinate(int x,int y){
            this.x=x;
            this.y=y;
        }
    }
    
    public static boolean isValid(int[][] grid,int i,int j){
        int m=grid.length,n=grid[0].length;
        return i>=0 && i<m && j>=0 && j<n && grid[i][j]==CC && !visited[i][j];
    }
    
    public static boolean isBorder(int[][] grid,int i,int j){
        int m=grid.length,n=grid[0].length;
        if(i==0 || i==m-1 || j==0 || j==n-1)
            return true;
        return grid[i-1][j]!=grid[i][j] || grid[i+1][j]!=grid[i][j] || grid[i][j-1]!=grid[i][j] || grid[i][j+1]!=grid[i][j];
        
    }
    
    public static int CC;
    public static boolean[][] visited;
    public int[][] colorBorder(int[][] grid, int r0, int c0, int color) 
    {
        int m=grid.length,n=grid[0].length;
        CC=grid[r0][c0];
        visited=new boolean[m][n];
        Queue<Coordinate> queue=new LinkedList<>();
        
        queue.add(new Coordinate(r0,c0));
        visited[r0][c0]=true;
        LinkedList<Coordinate> ans=new LinkedList();
        while(!queue.isEmpty())
        {
            Coordinate coor=queue.poll();
            int x=coor.x,y=coor.y;
            if(isBorder(grid,x,y))
                ans.add(coor);
            for(int dx=-1;dx<=1;dx++)
            {
                for(int dy=-1;dy<=1;dy++)
                {
                    if(Math.abs(dx+dy)==1 && isValid(grid,x+dx,y+dy))
                    {
                        queue.add(new Coordinate(x+dx,y+dy));
                        visited[x+dx][y+dy]=true;
                        System.out.println(x+dx);
                        System.out.println(y+dy);
                    }
                }
            }
        }
        for(Coordinate c:ans)
            grid[c.x][c.y]=color;
        return grid;
    }
}

1007. Minimum Domino Rotations For Equal Row
暴力枚举1,2,…,6在两排中需要旋转的次数,计算时需要两个计数变量来存储,最后得到最小值。

class Solution {
    public int minDominoRotations(int[] A, int[] B) {
        
        int ans=Integer.MAX_VALUE;
        for(int i=1;i<=6;i++)
        {
            int a1=0,a2=0;
            for(int j=0;j<A.length;j++){
                if(A[j]==i && B[j]!=i)
                    a2++;
                else if(A[j]!=i && B[j]==i)
                    a1++;
                else if(A[j]!=i && B[j]!=i)
                {
                    a1=Integer.MAX_VALUE;
                    a2=Integer.MAX_VALUE;
                    break;
                }   
            }
            ans=Math.min(ans,Math.min(a1,a2));
        }  
        return ans==Integer.MAX_VALUE?-1:ans;
    }
}

1008. Construct Binary Search Tree from Preorder Traversal
中规中矩的二叉搜索树的反序列化,类似于由中序遍历和后序遍历重建二叉树

class Solution {
    public TreeNode bstFromPreorder(int[] preorder) {
        return recursive(preorder,0,preorder.length-1);
    }
    
    public static TreeNode recursive(int[] preorder,int i,int j){
        
        if(i>j)
            return null;
        TreeNode node=new TreeNode(preorder[i]);
        int k=i+1;
        for(;k<=j;k++){
            if(preorder[k]>preorder[i])
                break;
        }
        node.left=recursive(preorder,i+1,k-1);
        node.right=recursive(preorder,k,j);
        return node;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值