算法训练Day29|* 491.递增子序列* 46.全排列* 47.全排列 II

LeetCode:491.递增子序列

491. 递增子序列 - 力扣(LeetCode)

1.思路:

创建两个全局变量,一个path收集符合条件的结果,另一个result收集所有符合条件的结果。
当path.size>=2时,符合条件:数量大于1,即刻加入result结果集中。
HashSet临时集合存储所有遍历过的元素,调用hs.contains()方法用于同一递归深度的树层去重!!!
for循环横向遍历实现广度搜索。

2.代码实现:
 1class Solution {
 2    List<List<Integer>> result = new ArrayList<>(); // 创建收集结果的结果集
 3    List<Integer> path = new ArrayList<>(); // 收集每个结果
 4    public List<List<Integer>> findSubsequences(int[] nums) {
 5        backtracking(nums, 0); // 回溯函数
 6        return result; // 返回结果集
 7    }
 8    public void backtracking(int[] nums, int startIndex) {
 9        if (path.size() > 1) { // 单个结果集的长度大于1时,即刻加入到结果集中
10            result.add(new ArrayList<>(path));
11        }
12        HashSet<Integer> hs = new HashSet<>(); // 临时的结合hs,用于树层去重
13        for (int i = startIndex; i < nums.length; i++) {
14            if (!path.isEmpty() && path.get(path.size() - 1) > nums[i] || hs.contains(nums[i])) { // 什么时候去重?树层元素相同时,①路径元素不为空且path中最后一个数值大于当前nums[i] ②同一深度的树层包含同个元素时去重
15                continue;
16            }
17            hs.add(nums[i]); // 收集所有遍历的元素
18            path.add(nums[i]); // 符合条件的元素加入路径中
19            backtracking(nums, i + 1); // 回溯函数继续深度遍历添加符合条件的元素
20            path.remove(path.size() - 1);  // 回溯:结束本层回溯函数,返回上一层继续
21        }
22    }
23}
3.复杂度分析:

时间复杂度:一个元素在回溯一层同时进行for循环和调用递归函数时间耗费为2倍,n层位2^n;n个元素则复杂度为O(n*2^n).
空间复杂度:栈堆空间开销,递归函数消耗栈,层数最大为N,此时时间复杂度为O(n).堆空间开销为集合O(n)。则整体为O(n).

LeetCode:46.全排列

46. 全排列 - 力扣(LeetCode)

1.思路:

回溯函数不用传入startIndex来限定位置了,直接循环遍历即可,当长度和数组长度相同时加入到结果集中。终止条件:直到path中出现相同元素结束本层循环,继续下一次循环。(终止条件为什么不能是path.size()>nums.length??)

2.代码实现:
 1//实现一:
 2class Solution {
 3    List<List<Integer>> result = new ArrayList<>();
 4    List<Integer> path = new ArrayList<>();
 5    public List<List<Integer>> permute(int[] nums) {
 6        backtracking(nums);
 7        return result;
 8    }
 9    public void backtracking(int[] nums) {
10        if (path.size() == nums.length) {
11            result.add(new ArrayList<>(path));
12        }
13        for (int i = 0; i < nums.length; i++) {
14            if (path.contains(nums[i])) {
15                continue;
16            }
17            path.add(nums[i]);
18            backtracking(nums);
19            path.remove(path.get(path.size() - 1));
20        }
21    }
22}

实现2

 1class Solution {
 2    List<List<Integer>> result = new ArrayList<>();
 3    LinkedList<Integer> path = new LinkedList<>();
 4    public List<List<Integer>> permute(int[] nums) {
 5        // if (num)
 6        backtracking(nums, path);
 7        return result;
 8    }
 9    public void backtracking(int[] nums, LinkedList<Integer> path) {
10        if (path.size() == nums.length) {
11            result.add(new ArrayList<>(path));
12        }
13        for (int i = 0; i < nums.length; i++) {
14            if (path.contains(nums[i])) { // 终止条件
15                continue;
16            }
17            path.add(nums[i]);
18            backtracking(nums, path);
19            path.removeLast();
20        }
21    }
22}
3.复杂度分析:

时间复杂度:一次遍历为n,n次遍历为n^2.为什么代码随想录给的是O(n!).
空间复杂度:栈开销O(n).堆开销为O(n).

LeetCode:47.全排列 II

47. 全排列 II - 力扣(LeetCode)

1.思路:
2.代码实现:
 1class Solution {
 2    List<List<Integer>> result = new ArrayList<>(); // 存储结果的结果集
 3    List<Integer> path = new ArrayList<>(); // 收集每个符合条件的结果
 4    public List<List<Integer>> permuteUnique(int[] nums) {
 5        boolean[] used = new boolean[nums.length]; // used[]做标记
 6        Arrays.fill(used, false); // 全部赋予false
 7        Arrays.sort(nums); // 排序,便于剪枝(优化搜索)
 8        backtracking(nums, used); // 回溯函数
 9        return result; // 返回结果集
10    }
11    public void backtracking(int[] nums, boolean[] used) {
12        if (path.size() == nums.length) { // 当临时收集的结果等于nums数组长度时,加入到结果集
13            result.add(new ArrayList<>(path)); 
14            return; // 返回上一层
15        }
16        // 横向遍历 
17        for (int i = 0; i < nums.length; i++) {
18            if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) { // 树层去重
19                continue;
20            }
21            if (used[i] == false) { // 没有遍历过 才进行加入操作
22                used[i] = true; // 置为true表明没有遍历过
23                path.add(nums[i]); // 加入到结果中
24                backtracking(nums, used); // 回溯函数,计息递归
25                path.remove(path.size() - 1); // 去重
26                used[i] = false; //从一下数开始,当前数置为false
27            }
28        }
29    }
30}
3.复杂度分析:

时间复杂度:O(n2^n).有疑问:代码随想录O(n!n).
空间复杂度:O(n).

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您可以将这些常量提取出来,并使用它们来计算方位角(azimuth)和仰角(elevation)。以下是一个示例代码: ```java import java.util.TimeZone; public class Main { private static final double MEAN_LONGITUDE_OFFSET = 4.894967873; private static final double MEAN_ANOMALY_COEFFICIENT = 0.01720197034; private static final double ECLIPTIC_LONGITUDE_COEFFICIENT_1 = 0.03342305518; private static final double ECLIPTIC_LONGITUDE_COEFFICIENT_2 = 0.0003490658504; private static final double OBLIQUITY_COEFFICIENT_1 = 0.4090877234; private static final double OBLIQUITY_COEFFICIENT_2 = 0.000000006981317008; private static final double SIDEREAL_COEFFICIENT_1 = 4.894961213; private static final double SIDEREAL_COEFFICIENT_2 = 6.300388099; public static void main(String[] args) { // 其他变量的定义和赋值 // Decimal hour of the day at Greenwich double greenwichtime = hour - timezone + minute / 60 + second / 3600; // Days from J2000, accurate from 1901 to 2099 double daynum = 367 * year - 7 * (year + (month + 9) / 12) / 4 + 275 * month / 9 + day - 730531.5 + greenwichtime / 24; //Mean longitude of the sun double mean_long = daynum * MEAN_ANOMALY_COEFFICIENT + MEAN_LONGITUDE_OFFSET; double mean_anom = daynum * MEAN_ANOMALY_COEFFICIENT + 6.240040768; double eclip_long = mean_long + ECLIPTIC_LONGITUDE_COEFFICIENT_1 * Math.sin(mean_anom) + ECLIPTIC_LONGITUDE_COEFFICIENT_2 * Math.sin(2 * mean_anom); double obliquity = OBLIQUITY_COEFFICIENT_1 - OBLIQUITY_COEFFICIENT_2 * daynum; double rasc = Math.atan2(Math.cos(obliquity) * Math.sin(eclip_long), Math.cos(eclip_long)); double decl = Math.asin(Math.sin(obliquity) * Math.sin(eclip_long)); double sidereal = SIDEREAL_COEFFICIENT_1 + SIDEREAL_COEFFICIENT_2 * daynum + rlon; double hour_ang = sidereal - rasc; double elevation = Math.asin(Math.sin(decl) * Math.sin(rlat) + Math.cos(decl) * Math.cos(rlat) * Math.cos(hour_ang)); //Local azimuth of the sun double azimuth = Math.atan2(-Math.cos(decl) * Math.cos(rlat) * Math.sin(hour_ang), Math.sin(decl) - Math.sin(rlat) * Math.sin(elevation)); azimuth = into_range(Math.toDegrees(azimuth), 0, 360); elevation = into_range(Math.toDegrees(elevation), -180, 180); // 其他操作 } private static double into_range(double value, double min, double max) { double range = max - min; return ((value - min) % range + range) % range + min; } } ``` 这样,您可以在计算方位角和仰角时直接使用这些常量,使代码更加易读和易于维护。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值