「LeetCode学习计划-编程能力入 门」

Leetcode 编程能力入门徽章最佳实践

基本数据类型

1523. 在区间范围内统计奇数数目
思路一:

  1. [low, high]上循环遍历
  2. 判断是不是奇数 <=> 是否能被2整除
  3. 返回函数为int,全局累加
class Solution {
    public int countOdds(int low, int high) {
        int ans = 0;
        for(int i = low; i <=high; i++ ){
            if (i % 2 != 0 ) ans++;
        }
        return ans;
    }
}

但是超时了。。。时间复杂度O(n)
所以我们需要判断如何准确用公式总结问题的规律,[3, 7]有三个奇数,

class Solution {
    public int countOdds(int low, int high) {
        return (high+1  >> 1) - (low >> 1);
    }
}

1491. 去掉最低工资和最高工资后的工资平均值
思路一:

  1. Arrays内置排序+遍历的方法
  2. 确定边界,排序后的第二个元素到倒数第二个
  3. sum为double类型,自动向上转型
class Solution {
    public double average(int[] salary) {
        int length = salary.length;
        int n = length - 2;
        double sum = 0;
        Arrays.sort(salary);
        for (int i = 1; i <= n; i++) {
            sum += salary[i];
        }
        return sum/n;
    }
}

但是排序对于空间复杂度要求较高,只击败了5%的用户
思路二:

  1. 用整数默认最大值初始化全局最小值,整数默认最小值初始化全局最大值,设置全局累加值sum
  2. 遍历的过程中更新最小值和最大值
  3. 用公式(sum-min-max)/(length-2)返回结果
class Solution {
    public double average(int[] salary) {
        double sum = 0;
        double maxValue = Integer.MIN_VALUE, minValue = Integer.MAX_VALUE;
        for (int num : salary) {
            sum += num;
            maxValue = Math.max(maxValue, num);
            minValue = Math.min(minValue, num);
        }
        return (sum - maxValue - minValue) / (salary.length - 2);
    }
}

运算符

191. 位1的个数
思路:

  1. int默认是有符号数,因此无法用取余进行操作,需要用按位与进行判别当前位是不是1,如果是结果就加上1,否则加0
  2. 每次右移1位
public class Solution {
    // you need to treat n as an unsigned value
    public int hammingWeight(int n) {
        int  ans = 0;
        for (int i = 1; i <= 32; i++){
            ans += n&1;
            n >>= 1;
        }
        return ans;
    }
}

1281. 整数的各位积和之差
思路:

  1. 取得十进制数每位上的数字(从后往前取)
  2. 算得累积, 和累加和
  3. 返回积与和的差值
class Solution {
    public int subtractProductAndSum(int n) {
        int area = 1;
        int sum = 0;
        while (n>0){
            int p = n%10;
            area *= p;
            sum += p;
            n /= 10;

        }
        return area-sum;

    }
}

条件语句

976. 三角形的最大周长
思路:

  1. 排好序从后往前找
  2. 如果能构成三角形,则返回周长
  3. 否则往前移一位
  4. 如果检索到开头,没有能构成三角形的,则返回0
class Solution {
    public int largestPerimeter(int[] A) {
        Arrays.sort(A);
        for (int i = A.length - 1; i >= 2; --i) {
            if (A[i - 2] + A[i - 1] > A[i]) {
                return A[i - 2] + A[i - 1] + A[i];
            }
        }
        return 0;
    }
}

1779. 找到最近的有相同 X 或 Y 坐标的点
思路:

  1. 需要两个确据变量最短曼哈顿距离的数组下标和最短曼哈顿距离
  2. 遍历二维数组
  3. 判断是不是有效点
  4. 判断有效点的曼哈顿距离是否小于当前最短曼哈顿距离,如果是的话更新最短曼哈顿距离的数组下标和最短曼哈顿距离
  5. 最终遍历完返回最短曼哈顿距离的数组下标
class Solution {
    public int nearestValidPoint(int x, int y, int[][] points) {
        int minIndex = -1;
        int minJuLi = Integer.MAX_VALUE;
        for(int i=0;i<points.length;i++){
            if(x==points[i][0]||y==points[i][1]){ //有效点
                int res = Math.abs(x-points[i][0])+Math.abs(y-points[i][1]);
                if(res<minJuLi){
                    minJuLi = res;
                    minIndex = i;
                }
            }
        }
        return minIndex;
    }
}

循环

1822. 数组元素积的符号

思路:

  1. 用异或进行进行取反,目的是为了保留符号位,同号得正(0),异号得负(1)
class Solution {
    public int arraySign(int[] nums) {
        // 相乘的符号
        int ans = 0;
        for (int i : nums) {
            if (i == 0) return 0;
            ans ^= i;
        }
        return ans >= 0? 1: -1; // 大于等于0的结果都是正数
    }
}

class Solution {
    public int arraySign(int[] nums) {
        int res = 1;
        for (int i : nums) {
            if (i == 0) return 0;
            if (i < 0) res *= -1;
            if (i> 0) res *= 1;
        }
        return res;
    }
}

1502. 判断能否形成等差数列
思路:

class Solution {
    public boolean canMakeArithmeticProgression(int[] arr) {
        Arrays.sort(arr);
        int diff = arr[1] -arr[0];
        int i = 0;
 
        while (i < arr.length-1) {
            if (arr[i+1] == (i+1) * diff + arr[0]) i++;
            else return false;

        }
        return true;
    }
}
202. 快乐数

思路:

  1. 使用 “快慢指针” 思想,找出循环:“快指针” 每次走两步,“慢指针” 每次走一步,当二者相等时,即为一个循环周期。此时,判断是不是因为 1 引起的循环,是的话就是快乐数,否则不是快乐数。

注意:此题不建议用集合记录每次的计算结果来判断是否进入循环,因为这个集合可能大到无法存储;另外,也不建议使用递归,同理,如果递归层次较深,会直接导致调用栈崩溃。不要因为这个题目给出的整数是 int 型而投机取巧。

public class Solution {
    public int squareSum(int n) {
        int sum = 0;
        while (n > 0) {
            int digit = n % 10;
            sum += digit * digit;
            n /= 10;
        }
        return sum;
    }

    public boolean isHappy(int n) {
        int slow = n, fast = squareSum(n);
        while (slow != fast){
            slow = squareSum(slow);
            fast = squareSum(squareSum(fast));
        };
        return slow == 1;
    }
}


1790. 仅执行一次字符串交换能否使两个字符串相等

class Solution {
    public boolean areAlmostEqual(String s1, String s2) {
        int i = 0;
        int count = 0;
        HashMap<Character, Character> dict = new HashMap<>();
        while (i < s1.length()){
            if (count > 2) return false;
            if (s1.charAt(i) != (s2.charAt(i))) {
                if (dict.containsKey(s2.charAt(i)) && s1.charAt(i) == dict.get(s2.charAt(i)))
                    dict.remove(s2.charAt(i));
                else
                    dict.put(s1.charAt(i), s2.charAt(i));
                count ++;
            }

            i++;

        }
    
        if (dict.size() == 0) return true;
        else return false;
    }
}

函数

589. N 叉树的前序遍历

class Solution {
    public List<Integer> preorder(Node root) {
        transverse(root);
        return res;
    }
    List<Integer> res = new LinkedList<>();
    void transverse(Node root){
        if(root == null) return;
        
        res.add(root.val);
        for (Node child: root.children){
            transverse(child);
        }
    }
}

496. 下一个更大元素 I
单调栈模板 实现了一个计算下一个更大元素的函数,这里可以直接复用。因为题目说 nums1 是 nums2 的子集,那么我们先把 nums2 中每个元素的下一个更大元素算出来存到一个映射里,然后再让 nums1 中的元素去查表即可。

class Solution {
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        // 记录 nums2 中每个元素的下一个更大元素
        int[] greater = nextGreaterElement(nums2);
        // 转化成映射:元素 x -> x 的下一个最大元素
        HashMap<Integer, Integer> greaterMap = new HashMap<>();
        for (int i = 0; i < nums2.length; i++) {
            greaterMap.put(nums2[i], greater[i]);
        }
        // nums1 是 nums2 的子集,所以根据 greaterMap 可以得到结果
        int[] res = new int[nums1.length];
        for (int i = 0; i < nums1.length; i++) {
            res[i] = greaterMap.get(nums1[i]);
        }
        return res;
    }
    
    // 计算 nums 中每个元素的下一个更大元素
    int[] nextGreaterElement(int[] nums) {
        int n = nums.length;
        // 存放答案的数组
        int[] res = new int[n];
        Stack<Integer> s = new Stack<>();
        // 倒着往栈里放
        for (int i = n - 1; i >= 0; i--) {
            // 判定个子高矮
            while (!s.isEmpty() && s.peek() <= nums[i]) {
                // 矮个起开,反正也被挡着了。。。
                s.pop();
            }
            // nums[i] 身后的下一个更大元素
            res[i] = s.isEmpty() ? -1 : s.peek();
            s.push(nums[i]);
        }
        return res;
    }
}
// 详细解析参见:
// https://labuladong.github.io/article/?qno=496

1232. 缀点成线
![image.png](https://img-blog.csdnimg.cn/img_convert/9e3b49325bfd85106a8a97c46f13ed90.png#clientId=uc28ca5f9-57a2-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=263&id=u6fc795a8&margin=[object Object]&name=image.png&originHeight=526&originWidth=1438&originalType=binary&ratio=1&rotation=0&showTitle=false&size=125335&status=done&style=none&taskId=u5d29873c-59b9-4649-9d34-54dab573c18&title=&width=719)

int deltaX = coordinates[0][0], deltaY = coordinates[0][1];
int n = coordinates.length;
for (int i = 0; i < n; i++) {
    coordinates[i][0] -= deltaX;
    coordinates[i][1] -= deltaY;
}
int A = coordinates[1][1], B = -coordinates[1][0];
for (int i = 2; i < n; i++) {
    int x = coordinates[i][0], y = coordinates[i][1];
    if (A * x + B * y != 0) {
        return false;
    }
}
        return true;

1588. 所有奇数长度子数组的和

class Solution {
    public int sumOddLengthSubarrays(int[] arr) {
        int sum = 0;
        int n = arr.length;
        for (int i = 0; i < n; i++) {
            int leftCount = i, rightCount = n - i - 1;
            int leftOdd = (leftCount + 1) / 2;
            int rightOdd = (rightCount + 1) / 2;
            int leftEven = leftCount / 2 + 1;
            int rightEven = rightCount / 2 + 1;
            sum += arr[i] * (leftOdd * rightOdd + leftEven * rightEven);
        }
        return sum;
        
        
    }
}

283. 移动零
思路:
可以直接复用 27. 移除元素 的解法,先移除所有 0,然后把最后的元素都置为 0,就相当于移动 0 的效果。

class Solution {
    public void moveZeroes(int[] nums) {
        int slow = 0, fast = 0;
        while(fast<nums.length){
            if(nums[fast]!=0) {
                nums[slow] = nums[fast];
                slow++;
            }
            fast++;
        }
        while(slow<nums.length){
            nums[slow] = 0;
            slow++;
        }
    }
}

1672. 最富有客户的资产总量

class Solution {
    public int maximumWealth(int[][] accounts) {
        int max = Integer.MIN_VALUE;
        for (int[] i: accounts){
            int sum = 0;
            for (int j: i){
                sum += j;
            }
            max = Math.max(max, sum);
        }
        return max;
    }
}

数组

1572. 矩阵对角线元素的和

class Solution {
    public int diagonalSum(int[][] mat) {
        int ans = 0;
        int n = mat.length;
        for (int i = 0; i < n; i++){
            for (int j = 0; j < n; j++){
                if (j == i || j == n - i - 1)
                    ans += mat[i][j];
            }
        }
        return ans;
    }
}

566. 重塑矩阵

class Solution {
    public int[][] matrixReshape(int[][] mat, int r, int c) {
        int m = mat.length;
        int n = mat[0].length;
        if (m * n != r * c) {
            return mat;
        }

        int[][] res = new int[r][c];
        int a = 0;
        int b = 0;

        for (int i = 0; i < r; i++) {
            for (int j = 0; j < c; j++) {
                if (b >= n) {
                    b = 0;
                    a++;
                }
                res[i][j] = mat[a][b];
                b++;
            }
        }
        return res;

    }
}

字符串

1768. 交替合并字符串

class Solution {
    public String mergeAlternately(String word1, String word2) {
        int len1 = word1.length();
        int len2 = word2.length();
        char [] ca = new char[len1+len2];
        int p = 0;
        int p1 = 0;
        while(p < ca.length) {
            if(len1 < len2 && p1 >= len1) {
                ca[p] = word2.charAt(p1);
            }
            else if(len1 > len2 && p1 >= len2) {
                ca[p] = word1.charAt(p1);
            } else{ 
                
                ca[p] = word1.charAt(p1);
                ca[++p] =  word2.charAt(p1);
                
            }
            p++;
            p1++;
        }
        
        return new String(ca);
    }
}

1678. 设计 Goal 解析器

class Solution {
    public String interpret(String command) {
        return command.replace("()", "o").replace("(al)", "al");
    }
}

389. 找不同

class Solution {
    public char findTheDifference(String s, String t) {
        int as = 0, at = 0;
        for (int i = 0; i < s.length(); ++i) {
            as += s.charAt(i);
        }
        for (int i = 0; i < t.length(); ++i) {
            at += t.charAt(i);
        }
        return (char) (at - as);
    }
}

709. 转换成小写字母

class Solution {
    public String toLowerCase(String s) {
        return s.toLowerCase();
    }
}

1309. 解码字母到整数映射

class Solution {
    public String freqAlphabets(String s) {
        StringBuilder ans = new StringBuilder();
        for(int i = 0; i < s.length(); i++) {
            if (s.indexOf('#', i) - i ==2 ) {
                ans.append((char)(Integer.parseInt(s.substring(i,i+2))+96));
                i+=2;
            } else {
                ans.append((char)(96+(s.charAt(i)-'0')));
            }
        }

        return ans.toString();
    }
}

953. 验证外星语词典

class Solution {
    public boolean isAlienSorted(String[] words, String order) {
        int[] index = new int[26];
        for (int i = 0; i < order.length(); ++i) {
            index[order.charAt(i) - 'a'] = i;
        }
        for (int i = 1; i < words.length; i++) {
            boolean valid = false;
            for (int j = 0; j < words[i - 1].length() && j < words[i].length(); j++) {
                int prev = index[words[i - 1].charAt(j) - 'a'];
                int curr = index[words[i].charAt(j) - 'a'];
                if (prev < curr) {
                    valid = true;
                    break;
                } else if (prev > curr) {
                    return false;
                }
            }
            if (!valid) {
                /* 比较两个字符串的长度 */
                if (words[i - 1].length() > words[i].length()) {
                    return false;
                }
            }
        }
        return true;

    }
}

链表 & 树

1290. 二进制链表转整数

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public int getDecimalValue(ListNode head) {
        int ans = head.val;
        while (head.next!=null) {ans <<= 1; head = head.next; ans+=head.val;}
        return ans;

    }
}

876. 链表的中间结点

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode middleNode(ListNode head) {
        // 快慢指针初始化指向 head
        ListNode slow = head, fast = head;
        // 快指针走到末尾时停止
        while (fast != null && fast.next != null) {
            // 慢指针走一步,快指针走两步
            slow = slow.next;
            fast = fast.next.next;
        }
        // 慢指针指向中点
        return slow;
    }
}

104. 二叉树的最大深度
思路:
动态规划

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int maxDepth(TreeNode root) {
        if(root == null) return 0;
        int leftMax = maxDepth(root.left);
        int rightMax = maxDepth(root.right);
        return 1+Math.max(leftMax, rightMax);
    }
}

404. 左叶子之和

class Solution {
    public int sumOfLeftLeaves(TreeNode root) {
        transverse(root);
        return sum;
    }
    int sum = 0;
    void transverse(TreeNode root){
        if (root == null) return;
        if (root.left != null && root.left.left == null && root.left.right == null) {
            sum += root.left.val;
        }
        transverse(root.left);
        transverse(root.right);

    }
}

容器&库

1356. 根据数字二进制下 1 的数目排序

class Solution {
    public int[] sortByBits(int[] arr) {
        int[] map = new int[arr.length];
        for (int i = 0; i < arr.length; i++) {
            map[i] = Integer.bitCount(arr[i]) * 10000000 + arr[i];
        }
        Arrays.sort(map);
        for (int i = 0; i < map.length; i++) {
            map[i] = map[i] % 10000000;
        }
        return map;
    }
}

232. 用栈实现队列

class MyQueue {
    private Stack<Integer> s1, s2;
    public MyQueue() {
        s1 = new Stack<Integer>();
        s2 = new Stack<Integer>();
    }
    
    public void push(int x) {
        s1.push(x);
    }
    
    public int pop() {
        peek();
        return s2.pop();
    }
    
    public int peek() {
        if(s2.isEmpty()){
            while(!s1.isEmpty())
                s2.push(s1.pop());
        }
        return s2.peek();
    }
    
    public boolean empty() {
        return s1.isEmpty() && s2.isEmpty();
    }
}

/**
 * Your MyQueue object will be instantiated and called as such:
 * MyQueue obj = new MyQueue();
 * obj.push(x);
 * int param_2 = obj.pop();
 * int param_3 = obj.peek();
 * boolean param_4 = obj.empty();
 */

242. 有效的字母异位词

class Solution {
    public boolean isAnagram(String s, String t) {
        int [] cnt = new int[26];
        if (s.length() != t.length()) return false;
        else {
            for (int i = 0; i < s.length(); i++){
                cnt[s.charAt(i)-'a']++;
            }
            for (int i = 0; i < t.length(); i++) {
                cnt[t.charAt(i)-'a']--;
                if (cnt[t.charAt(i)-'a'] < 0) return false;
            }
            return true;
        }
    }
}

217. 存在重复元素

class Solution {
    public boolean containsDuplicate(int[] nums) {
        HashSet<Integer> set = new HashSet<>();
        for (int i = 0; i < nums.length; i++){
            if (set.contains(nums[i])) return true;
            set.add(nums[i]);
        }
        return false;
    }
}

类 & 对象

1603. 设计停车系统

class ParkingSystem {
    Map<Integer, Integer> map = new HashMap<>();
    public ParkingSystem(int _big, int _medium, int _small) {
        map.put(1, _big);
        map.put(2, _medium);
        map.put(3, _small);
    }
    
    public boolean addCar(int ct) {
        if (map.get(ct) > 0) {
            map.put(ct, map.get(ct) - 1);
            return true;
        }
        return false;
    }
}

/**
 * Your ParkingSystem object will be instantiated and called as such:
 * ParkingSystem obj = new ParkingSystem(big, medium, small);
 * boolean param_1 = obj.addCar(carType);
 */

303. 区域和检索 - 数组不可变

class NumArray {
    private int[] preSum;
    public NumArray(int[] nums) {
        preSum = new int[nums.length+1];
        for(int i = 1; i < preSum.length; i++){
            preSum[i] = preSum[i-1] + nums[i-1];
        }
    }
    
    public int sumRange(int left, int right) {
        return preSum[right + 1] - preSum[left];
    }
}

/**
 * Your NumArray object will be instantiated and called as such:
 * NumArray obj = new NumArray(nums);
 * int param_1 = obj.sumRange(left,right);
 */
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值