Java每日一练(20230326)

简介: Java每日一练(20230326)

1. 括号生成


数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。


示例 1:

输入:n = 3

输出:["((()))","(()())","(())()","()(())","()()()"]


示例 2:

输入:n = 1

输出:["()"]


提示:

   1 <= n <= 8

出处:

https://edu.csdn.net/practice/23843565

代码:

import java.util.Stack;
import java.util.List;
import java.util.ArrayList;
public class generateParenthesis {
    public static class Solution {
        void gen(Stack<String> p, int lc, int rc, List<String> r, int n) {
            if (lc > n) {
                return;
            }
            if (lc == n && rc == n) {
                StringBuilder sb = new StringBuilder();
                for (String l : p) {
                    sb.append(l);
                }
                r.add(sb.toString());
            }
            p.push("(");
            lc++;
            gen(p, lc, rc, r, n);
            p.pop();
            lc--;
            if (lc > rc) {
                p.push(")");
                rc++;
                gen(p, lc, rc, r, n);
                p.pop();
                rc--;
            }
        }
        public List<String> generateParenthesis(int n) {
            List<String> results = new ArrayList<String>();
            Stack<String> p = new Stack<String>();
            gen(p, 0, 0, results, n);
            return results;
        }
    }
    public static void main(String[] args) {
        Solution s = new Solution();
        System.out.println(s.generateParenthesis(3));
        System.out.println(s.generateParenthesis(1));
        System.out.println(s.generateParenthesis(2));
    }
}

输出:

[((())), (()()), (())(), ()(()), ()()()]

[()]

[(()), ()()]

代码2:回溯法

import java.util.ArrayList;
import java.util.List;
public class generateParenthesis2 {
    public static class Solution {
        public List<String> generateParenthesis(int n) {
            List<String> res = new ArrayList<>();
            if (n <= 0) {
                return res;
            }
            backtrack(res, new StringBuilder(), 0, 0, n);
            return res;
        }
        private void backtrack(List<String> res, StringBuilder sb, int left, int right, int n) {
            if (sb.length() == n * 2) { // 已经添加了 n 对括号
                res.add(sb.toString());
                return;
            }
            if (left < n) { // 添加左括号
                sb.append("(");
                backtrack(res, sb, left + 1, right, n);
                sb.deleteCharAt(sb.length() - 1);
            }
            if (right < left) { // 添加右括号
                sb.append(")");
                backtrack(res, sb, left, right + 1, n);
                sb.deleteCharAt(sb.length() - 1);
            }
        }
    }
    public static void main(String[] args) {
        Solution s = new Solution();
        System.out.println(s.generateParenthesis(3));
        System.out.println(s.generateParenthesis(1));
        System.out.println(s.generateParenthesis(2));
    }
}

输出:

[((())), (()()), (())(), ()(()), ()()()]

[()]

[(()), ()()]

代码3: 动态规则

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class generateParenthesis3 {
    public static class Solution {
        public List<String> generateParenthesis(int n) {
            List<String> res = new ArrayList<>();
            if (n <= 0) {
                return res;
            }
            List<String>[] dp = new List[n + 1];
            dp[0] = Arrays.asList("");
            for (int i = 1; i <= n; i++) {
                List<String> list = new ArrayList<>();
                for (int j = 0; j < i; j++) {
                    List<String> s1 = dp[j];
                    List<String> s2 = dp[i - j - 1];
                    for (String str1 : s1) {
                        for (String str2 : s2) {
                            list.add("(" + str1 + ")" + str2);
                        }
                    }
                }
                dp[i] = list;
            }
            return dp[n];
        }
    }
    public static void main(String[] args) {
        Solution s = new Solution();
        System.out.println(s.generateParenthesis(3));
        System.out.println(s.generateParenthesis(1));
        System.out.println(s.generateParenthesis(2));
    }
}

输出:

[()()(), ()(()), (())(), (()()), ((()))]

[()]

[()(), (())]


2. 子集


给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。


示例 1:

输入:nums = [1,2,3]

输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]


示例 2:

输入:nums = [0]

输出:[[],[0]]


提示:

   1 <= nums.length <= 10

   -10 <= nums[i] <= 10

   nums 中的所有元素 互不相同


出处:

https://edu.csdn.net/practice/23843566


代码:回溯算法

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class subsets {
    public static class Solution {
        public List<List<Integer>> subsets(int[] nums) {
            List<List<Integer>> res = new ArrayList<List<Integer>>();
            List<Integer> tmp = new ArrayList<>();
            res.add(tmp);
            if (nums.length == 0)
                return res;
            helper(nums, 0, tmp, res);
            return res;
        }
        public void helper(int[] nums, int start, List<Integer> tmp, List<List<Integer>> res) {
            for (int i = start; i < nums.length; i++) {
                tmp.add(nums[i]);
                helper(nums, i + 1, tmp, res);
                res.add(new ArrayList<Integer>(tmp));
                tmp.remove(tmp.size() - 1);
            }
        }
    }
    private static int[] ArraySlice(int[] arr, int start, int end) {
        // 等价于: Arrays.copyOfRange(arr[], start, end)
        int[] slice = new int[end - start];
        for (int i = 0; i < slice.length; i++) {
            slice[i] = arr[start + i];
        }
        return slice;
    }
    public static void main(String[] args) {
        Solution s = new Solution();
        int[] nums = {1,2,3};
        System.out.println(s.subsets(nums));
        System.out.println(s.subsets(ArraySlice(nums,1,3)));
        System.out.println(s.subsets(ArraySlice(nums,0,1)));
        System.out.println(s.subsets(Arrays.copyOfRange(nums, 1, 3)));
        System.out.println(s.subsets(Arrays.copyOfRange(nums, 0, 1)));
    }
}


输出:

[[], [1, 2, 3], [1, 2], [1, 3], [1], [2, 3], [2], [3]]

[[], [2, 3], [2], [3]]

[[], [1]]

[[], [2, 3], [2], [3]]

[[], [1]]


代码2: 回溯算法

import java.util.ArrayList;
import java.util.List;
public class subsets {
    public static class Solution {
        public List<List<Integer>> subsets(int[] nums) {
            List<List<Integer>> res = new ArrayList<>();
            backtracking(res, nums, new ArrayList<>(), 0);
            return res;
        }
        private void backtracking(List<List<Integer>> res, int[] nums, List<Integer> subset, int start) {
            res.add(new ArrayList<>(subset)); // 将当前子集加入结果集
            for (int i = start; i < nums.length; i++) {
                subset.add(nums[i]); // 加入当前元素
                backtracking(res, nums, subset, i + 1); // 递归加入下一个元素
                subset.remove(subset.size() - 1); // 回溯,移除最后一个元素
            }
        }
    }
    private static int[] ArraySlice(int[] arr, int start, int end) {
        // 等价于: Arrays.copyOfRange(arr[], start, end)
        int[] slice = new int[end - start];
        for (int i = 0; i < slice.length; i++) {
            slice[i] = arr[start + i];
        }
        return slice;
    }
    public static void main(String[] args) {
        Solution s = new Solution();
        int[] nums = {1,2,3};
        System.out.println(s.subsets(nums));
        System.out.println(s.subsets(ArraySlice(nums,1,3)));
        System.out.println(s.subsets(ArraySlice(nums,0,1)));
    }
}


输出:

[[], [1], [1, 2], [1, 2, 3], [1, 3], [2], [2, 3], [3]]

[[], [2], [2, 3], [3]]

[[], [1]]

代码3:  迭代法

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class subsets {
    public static class Solution {
        public static List<List<Integer>> subsets(int[] nums) {
            List<List<Integer>> res = new ArrayList<>();
            res.add(new ArrayList<>()); // 加入空集
            for (int i = 0; i < nums.length; i++) {
                int size = res.size(); // 获取当前结果集的大小
                for (int j = 0; j < size; j++) {
                    List<Integer> subset = new ArrayList<>(res.get(j)); // 复制已有子集
                    subset.add(nums[i]); // 加入新元素
                    res.add(subset); // 加入结果集
                }
            }
            return res;
        }
    }
    public static void main(String[] args) {
        Solution s = new Solution();
        int[] nums = {1,2,3};
        System.out.println(s.subsets(nums));
        System.out.println(s.subsets(Arrays.copyOfRange(nums, 1, 3)));
        System.out.println(s.subsets(Arrays.copyOfRange(nums, 0, 1)));
    }
}



输出:

[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]

[[], [2], [3], [2, 3]]

[[], [1]]

代码4: 位运算

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class subsets {
    public static class Solution {
        public List<List<Integer>> subsets(int[] nums) {
            int n = nums.length;
            int m = 1 << n; // 共有2^n个子集
            List<List<Integer>> res = new ArrayList<>();
            for (int i = 0; i < m; i++) {
                List<Integer> subset = new ArrayList<>();
                for (int j = 0; j < n; j++) {
                    if (((i >> j) & 1) == 1) { // 判断第j位是否为1
                        subset.add(nums[j]); // 将第j个元素加入子集
                    }
                }
                res.add(subset); // 将当前子集加入结果集
            }
            return res;
        }
    }
    public static void main(String[] args) {
        Solution s = new Solution();
        int[] nums = {1,2,3};
        System.out.println(s.subsets(nums));
        System.out.println(s.subsets(Arrays.copyOfRange(nums, 1, 3)));
        System.out.println(s.subsets(Arrays.copyOfRange(nums, 0, 1)));
    }
}



输出:

[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]

[[], [2], [3], [2, 3]]

[[], [1]]


3. 分发糖果


老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。


你需要按照以下要求,帮助老师给这些孩子分发糖果:

   每个孩子至少分配到 1 个糖果。

   评分更高的孩子必须比他两侧的邻位孩子获得更多的糖果。


那么这样下来,老师至少需要准备多少颗糖果呢?


示例 1:

输入:[1,0,2]

输出:5

解释:你可以分别给这三个孩子分发 2、1、2 颗糖果。


示例 2:

输入:[1,2,2]

输出:4

解释:你可以分别给这三个孩子分发 1、2、1 颗糖果。

第三个孩子只得到 1 颗糖果,这已满足上述两个条件。


出处:

https://edu.csdn.net/practice/23843567

代码: 贪心算法

public class candy {
    public static class Solution {
        public int candy(int[] ratings) {
            int len = ratings.length;
            int[] left = new int[len];
            int[] right = new int[len];
            left[0] = 1;
            right[len - 1] = 1;
            for (int i = 1; i < len; i++) {
                if (ratings[i] > ratings[i - 1]) {
                    left[i] = left[i - 1] + 1;
                } else {
                    left[i] = 1;
                }
            }
            for (int i = len - 2; i >= 0; i--) {
                if (ratings[i] > ratings[i + 1]) {
                    right[i] = right[i + 1] + 1;
                } else {
                    right[i] = 1;
                }
            }
            int res = 0;
            for (int i = 0; i < len; i++) {
                res += Math.max(left[i], right[i]);
            }
            return res;
        }
    }
    public static void main(String[] args) {
        Solution s = new Solution();
        int[] nums = {1,0,2};
        System.out.println(s.candy(nums));
        int[] nums1 = {1,2,2};
        System.out.println(s.candy(nums1));
    }
}




输出:

5

4

代码2:原理一样,数组元素全部初始化为1,简化代码

import java.util.Arrays;
public class candy {
    public static class Solution {
        public int candy(int[] ratings) {
            int n = ratings.length;
            int[] candy = new int[n];
            Arrays.fill(candy, 1); // 每个孩子至少分配到 1 个糖果
            // 从左向右扫描,满足评分更高的孩子必须比他左侧的邻位孩子获得更多的糖果
            for (int i = 1; i < n; i++) {
                if (ratings[i] > ratings[i - 1]) {
                    candy[i] = candy[i - 1] + 1;
                }
            }
            // 从右向左扫描,满足评分更高的孩子必须比他右侧的邻位孩子获得更多的糖果
            for (int i = n - 2; i >= 0; i--) {
                if (ratings[i] > ratings[i + 1]) {
                    candy[i] = Math.max(candy[i], candy[i + 1] + 1);
                }
            }
            // 统计总共需要的糖果数
            int sum = 0;
            for (int i = 0; i < n; i++) {
                sum += candy[i];
            }
            return sum;
        }
    }
    public static void main(String[] args) {
        Solution s = new Solution();
        int[] nums = {1,0,2};
        System.out.println(s.candy(nums));
        int[] nums1 = {1,2,2};
        System.out.println(s.candy(nums1));
    }
}




目录
相关文章
CSDN每日一练(Java)--小艺的英文名
CSDN每日一练(Java)--小艺的英文名
|
安全 Java C++
2023-3-25 java选择题每日一练
2023-3-25 java选择题每日一练
91 1
|
Rust 索引
Rust 编程小技巧摘选(6)
Rust 编程小技巧摘选(6)
203 1
Rust 编程小技巧摘选(6)
|
C++ Python Rust
Rust 重载运算符|复数结构的“加减乘除”四则运算
Rust 重载运算符|复数结构的“加减乘除”四则运算
223 0
Rust 重载运算符|复数结构的“加减乘除”四则运算
|
Linux
Linux 终端命令之文件浏览(1) cat
Linux 终端命令之文件浏览(1) cat
129 0
Linux 终端命令之文件浏览(1) cat
|
Go Python Rust
Rust 编程小技巧摘选(7)
Rust 编程小技巧摘选(7)
250 0
Rust 编程小技巧摘选(7)
|
Linux Windows Ubuntu
Windows 使用 Linux 子系统,轻轻松松安装多个linux
Windows 使用 Linux 子系统,轻轻松松安装多个linux
1297 0
Windows 使用 Linux 子系统,轻轻松松安装多个linux
|
C++ Rust NoSQL
Rust 数据类型 之 类C枚举 c-like enum
Rust 数据类型 之 类C枚举 c-like enum
148 0
Rust 数据类型 之 类C枚举 c-like enum
|
Java Go C++
Golang每日一练(leetDay0120) 反转字符串中的元音字母、前K个高频元素
Golang每日一练(leetDay0120) 反转字符串中的元音字母、前K个高频元素
179 0
Golang每日一练(leetDay0120) 反转字符串中的元音字母、前K个高频元素
|
Java Go C++
Golang每日一练(leetDay0116) 路径交叉、回文对
Golang每日一练(leetDay0116) 路径交叉、回文对
110 0
Golang每日一练(leetDay0116) 路径交叉、回文对