【面试算法题总结14】空间换时间,时间换空间算法

本文总结了在面试中常见的空间换时间与时间换空间算法,通过实例解析了如何利用HashMap优化时间复杂度,包括两数之和、和为K的子数组等题目。还介绍了LRU和LFU缓存的实现策略,以及字母异位词分组的不同解法。
摘要由CSDN通过智能技术生成

空间换时间,时间换空间算法:

1 空间换时间:使用HashMap保存数据
 

例题1:两数之和

解法1:时间优先(HashMap)

时间复杂度:O(n)
空间复杂度:O(n)

class Solution {
   
    public int[] twoSum(int[] nums, int target) {
   
        Map<Integer,Integer> map=new HashMap<>();
        for(int i=0;i<nums.length;++i){
   
            int newTarget=target-nums[i];
            if(map.containsKey(newTarget)){
   
                return new int[]{
   map.get(newTarget),i};
            }
            map.put(nums[i],i);
        }
        return new int[2];
    }
}

解法2:空间优先(遍历所有情况)

时间复杂度:O(n^2)
空间复杂度:O(1)

class Solution {
   
    public int[] twoSum(int[] nums, int target) {
   
        for(int i=0;i<nums.length;++i){
   
            for(int j=i+1;j<nums.length;++j){
   
                int sum=nums[i]+nums[j];
                if(sum==target){
   
                    return new int[]{
   i,j};
                }
            }
        }
        return new int[2];
    }
}

不能先排序,再左右指针。这样排序的时候,原数据的下标数据就没了

 

例题2:和为 K 的子数组

HashMap保存前缀和,以及其出现次数

class Solution {
   
    public int subarraySum(int[] nums, int k) {
   
        int result=0;
        Map<Integer,Integer> map=new HashMap<Integer,Integer>();
        int sum=0;
        map.put(0, 1);
        for(int i=0;i<nums.length;++i){
   
            sum+=nums[i];
            int need=sum-k;
            if(map.containsKey(need)){
   
                result+=map.get(need);
            }
            map.put(sum,map.getOrDefault(sum,0)+1);
        }
        return result;
    }
}

 

例题3:路径总和 III

例题2的二叉树版本:
主要学习的题解:https://leetcode-cn.com/problems/path-sum-iii/solution/dui-qian-zhui-he-jie-fa-de-yi-dian-jie-s-dey6/

1 前缀和:一个节点的前缀和就是该节点到根之间的路径和
2 HashMap的key是前缀和, value是该前缀和的节点数量,记录数量是因为有出现复数路径的可能
3 本质还是空间换时间,保存各种前缀和出现的次数。
即:要寻找的前缀和=根节点到当前节点的路径和-targetSum

/**
 * 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 {
   
    int wholeTargetSum;
    Map<Integer,Integer> map;
    public int pathSum(TreeNode root, int targetSum) {
   
        wholeTargetSum=targetSum;
        map=new HashMap<>();
        map.put(0,1);    //十分重要的一行,不然就不能从根节点开始算了
        return dfs(root,0);
    }
    public int dfs(TreeNode root,int pre){
   
        if(root==null){
   
            return 0;
        }

        int pathSum=pre+root.val;   //获取节点到当前节点root的路径和pathSum
        int needPrefix=pathSum-wholeTargetSum;  //得到需要的前缀和needPrefix
        int count=map.getOrDefault(needPrefix,0);   //得到needPrefix对应次数

         /*添加该前缀和到map中,给子节点使用
          这行代码不能放在 int count=map.getOrDefault(needPrefix,0); 之前,因为路径不能不包括任何节点
          */
        map
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值