Map、栈、队列

Map的方法:

  1. clear:从映射中移除所有元素。
  2. delete:从映射中移除指定的元素。
  3. forEach:对映射中的每个元素执行指定操作。
  4. get:返回映射中的指定元素。
  5. has:如果映射包含指定元素,则返回 true。
  6. set:添加一个新建元素到映射。
  7. toString:返回映射的字符串表示形式。
  8. valueOf:返回指定对象的原始值。
  9. Object.getOwnPropertyNames(map).length:获取map的长度
  10. 遍历Map:
    (1)keys():返回键名的遍历器。
    (2)values():返回键值的遍历器。
    (3)entries():返回所有成员的遍历器。
    (4)forEach():遍历 Map 的所有成员。
let a = new Map([
    ['name','leo'],
    ['age',18]
])

for (let i of a.keys()){...};
for (let i of a.values()){...};
for (let i of a.entries()){...};
a.forEach((v,k,m)=>{
    console.log(`key:${k},value:${v},map:${m}`)
})

Set的方法:

  1. 创建 Set
    (1)new Set()方式创建:let v = new Set()
    (2)通过传入数组方式创建:let v = new Set([1,2,3,3,5])
  2. add:添加元素
  3. delete:删除元素
  4. size:获取set中元素个数
  5. has: 判断 Set 中是否包含某个元素
  6. 遍历 Set
    (1)forEach形式
let v = new Set()
v.add(1)
v.add(5)
v.forEach(t=>{
    console.log(t)
})

(2)for of 形式

let v = new Set([1,2,3,3,5])			
for(let t of v) {
    console.log(t)
}
  1. Set转换成数组:使用 Array.from 方法
let v = new Set([1,2,3,3,5])
let a = Array.from(v)

1. 两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。

示例1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例3:
输入:nums = [3,3], target = 6
输出:[0,1]

解:
1.在这里插入图片描述
2.在这里插入图片描述
3.在这里插入图片描述
4.在这里插入图片描述
5.代码如下:

var twoSum = function(nums, target) {
    let map = new Map();
    for(let i = 0, len = nums.length; i < len; i++){
        if(map.has(target - nums[i])){
            return [map.get(target - nums[i]), i];
        }else{
            map.set(nums[i], i);
        }
    }
    return [];
};

20. 有效的括号

给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。

示例 1:
输入:s = “()”
输出:true
示例 2:
输入:s = “()[]{}”
输出:true
示例 3:
输入:s = “(]”
输出:false
示例 4:
输入:s = “([)]”
输出:false
示例 5:
输入:s = “{[]}”
输出:true

解:
1.用map来保存 ‘(’,’)’,’{’,’}’,’[’,’]’ 用以匹配
2.遍历s 遇到 ‘(’,’{’,’[’ 就存入数组 遇到 ’)’,’}’,’]’ 就弹出数组(取数组最后一个)来比较 若一样则为true 继续遍历 不一样则返回false
3.最后遍历完了 若数组为空 代表所有的都匹配上了 才返回true
代码如下:
JAVA:

	public boolean isValid1(String s) {
        while (s.contains("{}") || s.contains("[]") || s.contains("()")){
            s = s.replace("{}","");
            s = s.replace("[]","");
            s = s.replace("()","");
        }
        return s.isEmpty();
    }

    public boolean isValid2(String s) {
        Stack<Character> stack = new Stack<>();

        int len = s.length();
        for (int i = 0; i < len; i++) {
            char c = s.charAt(i);
            if (c == '(' || c == '{' || c == '['){
                stack.push(c);
            }else{
                if (stack.isEmpty()) return  false;
                char left = stack.pop();
                if (left == '(' && c != ')') return false;
                if (left == '{' && c != '}') return false;
                if (left == '[' && c != ']') return false;
            }
        }
        return stack.isEmpty();
    }

    private static HashMap<Character,Character> map = new HashMap<>();
    static {//key==value
        map.put('(',')');
        map.put('[',']');
        map.put('{','}');
    }
    public boolean isValid3(String s) {
        Stack<Character> stack = new Stack<>();
        int len = s.length();
        for (int i = 0; i < len; i++) {
            char c = s.charAt(i);
            if (map.containsKey(c)){//若c是map的key 即c是左括号
                stack.push(c);
            }else{//c是右括号
                if (stack.isEmpty()) return  false;
                if (c != (map.get(stack.pop()))) return false;//stack.pop()是左括号 是key map.get(left) 根据key获取map中的值
                // 根据左括号获取对应的右括号 右括号不等于栈顶弹出来的左括号 则不配对
            }
        }
        return stack.isEmpty();
    }

JS:

var isValid = function(s) {
    if (s.length % 2 !== 0) return false;
    let stack = [];
    let p;
    let map = new Map();
    map.set('(', ')');
    map.set('[', ']');
    map.set('{', '}');
    for (let i = 0; i < s.length; i++) {
        if (map.has(s[i])) {
            stack.push(s[i]);
        }else if (s[i] === ')' || s[i] === ']' || s[i] === '}') {
            p = stack.pop();
            if (s[i] !== map.get(p)){
                return false;
            }
        }else {
            return false;
        }
    }
    return stack.length === 0;
};

149. 直线上最多的点数

给定一个二维平面,平面上有 n 个点,求最多有多少个点在同一条直线上。

示例1:
输入: [[1,1],[2,2],[3,3]]
输出: 3
在这里插入图片描述
示例 2:
输入: [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]
输出: 4
在这里插入图片描述

解:
1.使用枚举 只计算当前点i与当前点之后的点j的斜率
2.为每一个当前点i设置一个map map中的键是:i与j的斜率k(斜率计算公式:k = (y1 - y2) / (x1 - x2)) 值是k出现的次数
3.注意分母为0的情况 此时直线为x = b 在map中存入的键是最大值的对象用于区分 对于直线y = b 此时k = 0 map中存入键为0的对象用以区分
4.j遍历完了 该遍历下一个i了 又会新建一个map 所以j遍历结束后要遍历当前map 将最大的value 也就是k出现的次数存入res变量 最后输出res
5.以示例1为例 [1,1]的map的键为1 值为3 [2,2]的map的键为1 值为2 [3,3]的map的键为1 值为1 最后输出3 如果只用一个map的话 会输出4 会产生冗余 所以一定要给每一个点设置一个map
6.JS中最大的数字:Number.MAX_VALUE 最小的值:Number.MIN_VALUE
代码如下:

var maxPoints = function(points) {
    if (points.length <= 2) return points.length;
    let res = 2;
    let k;
    let num;
    let x;
    let y;
    for (let i = 0; i < points.length - 1; i++) {
        let map = new Map();
        for (let j = i + 1; j < points.length; j++) {
            x = points[i][0] - points[j][0];
            y = points[i][1] - points[j][1];
            k = x === 0 ? Number.MAX_VALUE : y / x;
            if (map.has(k)) {
                num = map.get(k) + 1;
                map.set(k, num);
            }else {
                map.set(k, 2);
            }
        }
        map.forEach((value,key) => {
            res = Math.max(res,value);
        })
    }

    return res;
};

在这里插入图片描述

146. LRU 缓存机制

运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制 。
实现 LRUCache 类:

  1. LRUCache(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存
  2. int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
  3. void put(int key, int value) 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字-值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。

LRU:是Least Recently Used的缩写,即最近最少使用,是一种常用的页面置换算法,选择最近最久未使用的页面予以淘汰。该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间 t,当须淘汰一个页面时,选择现有页面中其 t 值最大的,即最近最少使用的页面予以淘汰。
解:

/**
 * @param {number} capacity
 */
var LRUCache = function(capacity) {
    this.map = new Map();
    this.capacity = capacity;
};

/** 
 * @param {number} key
 * @return {number}
 */
LRUCache.prototype.get = function(key) {
    if (this.map.has(key)) {
        let v = this.map.get(key);
        this.map.delete(key);
        this.map.set(key,v);
        return v;
    }
    else return -1;
};

/** 
 * @param {number} key 
 * @param {number} value
 * @return {void}
 */
LRUCache.prototype.put = function(key, value) {
    if (this.map.has(key)) {
        this.map.delete(key);
        this.map.set(key,value);
        return;
    }
    if (this.map.size === this.capacity) {
        this.map.delete(this.map.keys().next().value);
    } 
    this.map.set(key,value);
};

剑指 Offer 09. 用两个栈实现队列

用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
解:首先,两个栈分工不同,一个为入队栈,一个为出队栈,各自负责入队和出队。入队操作,直接压入入队栈即可,出队操作需要优先检查出队栈是否有数据,若无,需要从入队栈倒入后再操作。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
代码如下:

var CQueue = function() {
    this.stackA = [];
    this.stackB = [];
};

CQueue.prototype.appendTail = function(value) {
    this.stackA.push(value);
};

CQueue.prototype.deleteHead = function() {
    if(this.stackB.length){
        return this.stackB.pop();
    }else{
        while(this.stackA.length){
            this.stackB.push(this.stackA.pop());
        }
        if(!this.stackB.length){
            return -1;
        }else{
            return this.stackB.pop();
        }
    }
};

剑指 Offer 30. 包含min函数的栈

定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数,调用 min、push 及 pop 的时间复杂度都是 O(1)。

示例:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.min(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.min(); --> 返回 -2.

解:根据题意,我们需要在常量级的时间内找到最小值!这说明,我们绝不能在需要最小值的时候,再做排序,查找等操作来获取!所以,我们可以创建两个栈,一个栈是主栈 stack,另一个是辅助栈 minStack,用于存放对应主栈不同时期的最小值。
在这里插入图片描述
在这里插入图片描述
因为-2<0 所以minStack中存入-2
在这里插入图片描述
因为-3<-2 所以minStack中存入-3
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
代码如下:
JS:

var MinStack = function() {
    this.x_stack = [];
    this.min_stack = [Infinity];
};

MinStack.prototype.push = function(x) {
    this.x_stack.push(x);
    this.min_stack.push(Math.min(this.min_stack[this.min_stack.length - 1], x));
};

MinStack.prototype.pop = function() {
    this.x_stack.pop();
    this.min_stack.pop();
};

MinStack.prototype.top = function() {
    return this.x_stack[this.x_stack.length - 1];
};

MinStack.prototype.min = function() {
    return this.min_stack[this.min_stack.length - 1];
};

剑指 Offer 31. 栈的压入、弹出序列

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。

示例 1:
输入:pushed = [1,2,3,4,5], popped = [4,5,3,2,1]
输出:true
解释:我们可以按以下顺序执行:
push(1), push(2), push(3), push(4), pop() -> 4,
push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1
示例 2:
输入:pushed = [1,2,3,4,5], popped = [4,3,5,1,2]
输出:false
解释:1 不能在 2 之前弹出。

解:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

剑指 Offer 50. 第一个只出现一次的字符

在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。

示例:1
s = “abaccdeff”
返回 “b”
示例 2
s = “”
返回 " "

解:
遍历字符串 将字符及字符出现的次数存入map 遍历map 返回值为1的键 若没有 则返回" "

map遍历:for (const [key, val] of map) { if (val === 1) { return key; } }

代码如下:
JS:

var firstUniqChar = function(s) {
    if (!s) return " ";
    let map = new Map();
    let char;
    for (let i = 0; i < s.length; i++) {
        let v = 1;
        char = s.charAt(i);
        if (map.has(char)){
            v = map.get(char) + 1;
        }
        map.set(char, v);
    }
    for (const [key, val] of map) {
        if (val === 1) {
            return key;
        }
    }
    return " "
};

剑指 Offer 50. 第一个只出现一次的字符

在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).(从0开始计数)
解:遍历字符串 将字符及字符出现的次数保存在count数组(保存在map也行)遍历数组 去count中查找字符 若该字符对应的值为1 则返回索引
代码如下:
JAVA:

public class Solution {
    public int FirstNotRepeatingChar(String str) {
        if(str==null || str.length() == 0)return -1;
        int[] count = new int[256];
        //用一个类似hash的东西来存储字符出现的次数,很方便
        for(int i=0; i < str.length();i++) {
        	count[str.charAt(i)]++;
       	}
        for(int i=0; i < str.length();i++) {
            if(count[str.charAt(i)]==1)
                return i;
        }
        return -1;
    }
}

JS:长见识了 竟然可以通过map[]来取值

function FirstNotRepeatingChar(str){
    const  map = new Map()
    for(let i of str){
        map[i] = (map[i]||0) +1
    } 
    for(let i in str){
        if(map[str[i]] == 1) return i
    }
    return -1  
}

剑指 Offer 03. 数组中重复的数字

在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

示例 1:
输入:[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3

解:
方法一:用set 遍历数组 若set中存在该元素说明该元素重复 直接返回该元素 若不存在 则加入set
代码如下:
JS:

var findRepeatNumber = function(nums) {
    let set = new Set();
    let num;
    for (let i = 0; i < nums.length; i++) {
        num = nums[i];
        if (set.has(num)) {
            return num;
        }else {
            set.add(num);
        }
    }
    return -1;
};

优化)方法二:原地交换 在一个长度为n的数组nums里 所有数字都在0~n-1的范围内 所以索引和数字应该一一对应 我们可以遍历数组 若元素大小===索引大小 直接跳过 不操作 若不相等 将元素放在对应索引处 在放之前判断一下该索引下的元素大小是否等于索引大小 若不相等直接放置 若相等 代表该元素重复 返回该元素
代码如下:
JAVA:

class Solution {
    public int findRepeatNumber(int[] nums) {
        int i = 0;
        while(i < nums.length) {
            if(nums[i] == i) {
                i++;
                continue;
            }
            if(nums[nums[i]] == nums[i]) return nums[i];
            int tmp = nums[i];
            nums[i] = nums[tmp];
            nums[tmp] = tmp;
        }
        return -1;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值