算法-其它

一、数学推导

1、平方根

牛顿迭代法

class Solution {
    public int mySqrt(int x) {
        double guess = x;
        double lastGuess;
        do {
            //牛顿-拉夫森迭代法
            lastGuess = guess;
            guess = (guess + x / guess) / 2;
        } while (Math.abs(guess - lastGuess) > 0.1);
        return (int)guess;
    }
}

二、前缀和

1、和为k的子数组

  • 题目

    • 给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。子数组是数组中元素的连续非空序列。

  • 思路

    • 使用前缀和的方法可以解决这个问题,因为我们需要找到和为k的连续子数组的个数。通过计算前缀和,我们可以将问题转化为求解两个前缀和之差等于k的情况。假设数组的前缀和数组为prefixSum,其中prefixSum[i]表示从数组起始位置到第i个位置的元素之和。那么对于任意的两个下标i和j(i < j),如果prefixSum[j] - prefixSum[i] = k,即从第i个位置到第j个位置的元素之和等于k,那么说明从第i+1个位置到第j个位置的连续子数组的和为k。通过遍历数组,计算每个位置的前缀和,并使用一个哈希表来存储每个前缀和出现的次数。在遍历的过程中,我们检查是否存在prefixSum[j] - k的前缀和,如果存在,说明从某个位置到当前位置的连续子数组的和为k,我们将对应的次数累加到结果中。这样,通过遍历一次数组,我们可以统计出和为k的连续子数组的个数,并且时间复杂度为O(n),其中n为数组的长度。
       
  • 题解

    class Solution {
        public int subarraySum(int[] nums, int k) {
            // 前缀和
            Map<Integer, Integer> map = new HashMap<>();
            int sum = 0;
            int count = 0;
            map.put(0, 1);
            for (int num : nums) {
                sum += num;
                if (map.containsKey(sum - k)) {
                    count += map.get(sum - k);
                }
                map.put(sum, map.getOrDefault(sum, 0) + 1);
            }
            return count;
        }
    }

    2、路径总和III

    • 题目
      • 给定一个二叉树的根节点 root ,和一个整数 targetSum ,求该二叉树里节点值之和等于 targetSum 的 路径 的数目。
    • 思路:DFS/前缀和
    • 题解
      class Solution {
          int ans = 0;
          //用哈希表统计 <前缀和, 个数>
          Map<Long, Integer> map = new HashMap<>();
          public int pathSum(TreeNode root, int targetSum) {
              map.put(0l, 1);
              dfs(root, 0l, targetSum);
              return ans;
          }
          public void dfs(TreeNode root,long sum, int targetSum) {
              if (root == null) {
                  return;
              }
              //计算当前的前缀和
              sum += root.val;
              //若存在前缀和sum - targetSum的路径
              //sum - (sum - targetSum)的路径就是所求路径
              ans += map.getOrDefault(sum - targetSum, 0);
              //将当前的前缀和加入map中
              map.put(sum, map.getOrDefault(sum, 0) + 1);
              //递归调用left&right
              dfs(root.left, sum, targetSum);
              dfs(root.right, sum, targetSum);
              //遍历结束要移除当前的前缀和
              map.put(sum, map.get(sum) - 1);
          }
      }

三、滑动窗口

1、找到字符串中所有字母异位词

  • 题目
    • 给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
  • 思路
  • 题解
    class Solution {
        public List<Integer> findAnagrams(String s, String p) {
    
            // 空间复杂度O(26)
            // 时间复杂度O(m + 26 * (n - m))
            List<Integer> list = new ArrayList<>();
            int[] s1 = new int[26];
            int[] p1 = new int[26];
            // 建立两个数组存放字符串中字母出现的词频,并以此作为标准比较
            // 当滑动窗口的首位在s[0]处时 (相当于放置滑动窗口进入数组)
            for (int i = 0; i < p.length(); i++) {
                s1[s.charAt(i) - 'a']++;
                p1[p.charAt(i) - 'a']++;
            }
            // 判断0放置处是否有异位词 (在放置时只需判断一次)
            if (Arrays.equals(s1, p1)) {
                list.add(0);
            }
             开始让窗口进行滑动,i是滑动前的首位
            for (int i = 0; i < s.length() - p.length(); i++) {
                // 将滑动前首位的词频删去
                s1[s.charAt(i) - 'a']--;
                // 增加滑动后最后一位的词频(以此达到滑动的效果)
                s1[s.charAt(i + p.length()) - 'a']++;
                // 进行判断
                if (Arrays.equals(s1, p1)) {
                    list.add(i + 1);
                }
            }
            return list;
        }
    }

四、非常规题

1、三种单例模式的实现

2、约瑟夫环

3、两个线程打印奇偶

4、LRU缓存实现

5、Java实现栈

6、加权轮询算法

7、死锁

8、快排

9、生产者消费者

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值