头像

ZJ.cao

河北科技师范学院




离线:1天前


最近来访(83)
用户头像
玊_8
用户头像
nut96
用户头像
我们_0
用户头像
yxc
用户头像
余火
用户头像
沐星不仙了
用户头像
十六夜咲夜
用户头像
Kirin_GT
用户头像
散兵
用户头像
妮可_4
用户头像
安_65
用户头像
咖喱鸡排饭
用户头像
TheShyFan
用户头像
chunluren
用户头像
Bin.
用户头像
清水洗脸
用户头像
垫底抽风
用户头像
lzs0511
用户头像
空银子
用户头像
cyb-包子

活动打卡代码 LeetCode 859. 亲密字符串

ZJ.cao
13天前
/**
 * @param {string} s
 * @param {string} goal
 * @return {boolean}
 */
var buddyStrings = function(s, goal) {
    const n = s.length,m = goal.length;
    let cnt=0,s1,s2,g1,g2;
    const map = new Map();
    if(n != m) return false;
    if(s == goal){
        for(let i = 0; i < n; i ++) {
            map.set(s[i],map.has(s[i])?map.get(s[i])+1:1);
            if(map.get(s[i])>=2) return true;
        }
        return false;
    }
    for(let i = 0; i < n; i ++) {
        if(s[i]!=goal[i]) {
            cnt++;
            if(cnt == 1){
                s1 = s[i];g1=goal[i];
            }else if(cnt == 2) {
                s2 = s[i];g2=goal[i];
            }
        }
        if(cnt == 3) return false;
    }
    if(s1==g2&&s2==g1) return true;
    return false;
};



ZJ.cao
15天前
/**
 * // Definition for a Node.
 * function Node(val,children) {
 *    this.val = val;
 *    this.children = children;
 * };
 */

/**
 * @param {Node|null} root
 * @return {number}
 */
var maxDepth = function(root) {
    if(!root) return 0;
    let ans = 0;
    const queue = [];
    queue.push(root);
    while(queue.length) {
        let size = queue.length;
        while (size > 0) {
            const node = queue.shift();
            const children = node.children;
            for (const child of children) {
                queue.push(child);
            }
            size--;
        }
        ans++;
    }
    return ans;
};



ZJ.cao
15天前
/**
 * @param {number[]} nums
 * @return {number}
 */
var findLHS = function(nums) {
    const map = new Map();
    let ans = 0;
    nums.forEach(x=>{
        map.set(x,map.has(x)?map.get(x)+1:1);
    });
    for(let item of map) {
        if(map.has(item[0]-1)) {
            ans = Math.max(ans,item[1]+map.get(item[0]-1));
        }
    }
    return ans;
};


活动打卡代码 LeetCode 15. 三数之和

ZJ.cao
18天前
/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var threeSum = function(nums) {
    const ans = [];
    nums.sort((a,b)=>a-b);
    for(let i = 0; i < nums.length; i ++) {
        //去重
        if(i&&nums[i]==nums[i-1]) continue;
        for(let j = i+1,k = nums.length-1; j < k; j ++) {
            //去重
            if(j > i+1&&nums[j]==nums[j-1]) continue;
            while(j<k-1&&nums[i]+nums[j]+nums[k-1]>=0) k--;
            if(nums[i]+nums[j]+nums[k]==0) {
                ans.push([nums[i],nums[j],nums[k]]);
            }
        }
    }
    return ans;
};


活动打卡代码 LeetCode 6. Z 字形变换

ZJ.cao
18天前
/**
 * @param {string} s
 * @param {number} numRows
 * @return {string}
 */
var convert = function(s, numRows) {
    if(numRows == 1) return s;
    let t = 0,flag = true;
    let arr = new Array();
    for(let i = 0; i < numRows; i ++) arr[i] = new Array();
    for(let i = 0; i < s.length; i ++) {
        if(flag) {
            t ++;
            if(t == numRows) flag = false;
        }else {
            t --;
            if(t == 1) flag = true;
        }
        arr[t-1].push(s[i]);
    }
    let ans="";
    for(let i = 0; i < numRows; i ++) {
        for(let j = 0; j < arr[i].length; j ++) {
            ans+=arr[i][j];
        }
    }
    return ans;
};



ZJ.cao
19天前
/**
 * @param {string[]} words
 * @return {number}
 */
var maxProduct = function(words) {
   const len = words.length;
    let bits = new Array(len).fill(0);
    for(let i = 0; i < len; i++){
        for(let char of words[i]){
            bits[i] |= 1 << (char.charCodeAt() - 97);
        }
    }

    let res = 0;
    for(let i = 0; i < len - 1; i++){
        for(let j = i+1; j < len; j++) {
            if((bits[i] & bits[j]) === 0) {
                res = Math.max(res, words[i].length * words[j].length);
            }
        }
    }
    return res;
};



ZJ.cao
22天前

1.什么是「闭包」。

2.「闭包」的作用是什么。

EAE9E1616769BDF8C0828A601A4D99AB.jpg
假设上面三行代码在一个立即执行函数中(为简明起见,我就不写立即执行函数了,影响读者理解)。

三行代码中,有一个局部变量 local,有一个函数 foofoo 里面可以访问到 local 变量。

好了这就是一个闭包:

「函数」和「函数内部能访问到的变量」的总和,就是一个闭包。
就这么简单。

有的同学就疑惑了,闭包这么简单么?

「我听说闭包是需要函数套函数,然后 return 一个函数的呀!」

比如这样:

function foo() {
    var local = 1;
    function bar() {
        local++;
        return local;
    }
    return bar;
}
var func = foo();
func();

这里面确实有闭包,local 变量和 bar 函数就组成了一个闭包(Closure)


为什么要函数套函数呢?

是因为需要局部变量,所以才把 local 放在一个函数里,如果不把 local 放在一个函数里,local 就是一个全局变量了,达不到使用闭包的目的——隐藏变量(等会会讲)。

这也是为什么我上面要说「运行在一个立即执行函数中」。

有些人看到「闭包」这个名字,就一定觉得要用什么包起来才行。其实这是翻译问题,闭包的原文是 Closure,跟「包」没有任何关系。

所以函数套函数只是为了造出一个局部变量,跟闭包无关。


为什么要 return bar 呢?

因为如果不 return,你就无法使用这个闭包。把 return bar 改成 window.bar = bar 也是一样的,只要让外面可以访问到这个 bar 函数就行了。

所以 return bar 只是为了 bar 能被使用,也跟闭包无关。


闭包的作用

闭包常常用来「间接访问一个变量」。换句话说,「隐藏一个变量」。

假设我们在做一个游戏,在写其中关于「还剩几条命」的代码。

如果不用闭包,你可以直接用一个全局变量:

window.lives = 30 //还剩30条命

这样看起来很不妥。万一不小心把这个值改成 -1 了怎么办。所以我们不能让别人「直接访问」这个变量。怎么办呢?
用局部变量。

但是用局部变量别人又访问不到,怎么办呢?

暴露一个访问器(函数),让别人可以「间接访问」。

代码如下:

!function() {
    var lives = 30;

    window.奖励一条命 = function() {
        lives += 1;
    }

    window.死一条命 = function() {
        lives -= 1;
    }
}()

简明起见,我用了中文 :)

那么在其他的 JS 文件,就可以使用 window.奖励一条命() 来涨命,使用 window.死一条命() 来让角色掉一条命。

看到闭包在哪了吗?

3C9A699EFCF983D941BF3E18BCD9A4D4.jpg
EAE9E1616769BDF8C0828A601A4D99AB.jpg
第一句是变量声明,第二句是函数声明,第三句是 console.log

每一句我都学过,为什么合起来我就看不出来是闭包?

我告诉你答案,你根本不需要知道闭包这个概念,一样可以使用闭包!

闭包是 JS 函数作用域的副产品。

换句话说,正是由于 JS 的函数内部可以使用函数外部的变量,所以这段代码正好符合了闭包的定义。而不是 JS 故意要使用闭包。

很多编程语言也支持闭包,另外有一些语言则不支持闭包。

只要你懂了 JS 的作用域,你自然而然就懂了闭包,即使你不知道那就是闭包!


这里 食用更佳



分享 JS原型链

ZJ.cao
1个月前

一、原型 prototype__proto__

  • 每个对象都有一个__proto__属性指向它的prototype原型对象
  • 每个构造函数都有一个prototype原型对象
  • prototype原型对象里的constructor指向构造器本身

那么我们为啥要引入原型对象prototype这个概念呢?
实际上通过构造函数创建对象时,可能有一些属性或者方法是不用修改的,比如下面这个程序

function Person(name,age) {
            this.name = name;
            this.age = age;
            this.say = function() {
                console.log("我会说话");
            }
        }
        var xm = new Star("小明",18);
        var xl = new Star("小亮",19);
        console.log(xm.say === xl.say); //false

结果是false,说明他俩的say方法不是同一个,也就是占用不同的内存空间。而我们的原型对象很好的解决了这一问题,实现了对属性和方法的共享


那么我们可以将程序修改成下面这样

function Person(name,age) {
            this.name = name;
            this.age = age;
        }
        Person.prototype.say = function() {
            console.log("我会说话");
        }
        var xm = new Star("小明",18);
        var xl = new Star("小亮",19);
        console.log(xm.say); //我会说话

那么我们xm对象本身没有这个方法,是咋找到的呢?
大家可以回看上面,对象都会有一个属性__proto__指向构造函数的prototype原型对象,之所以我们对象可以使用构造函数的prototype原型对象的属性和方法,就是因为有__proto__原型的存在

console.log(xm.__proto__ === Person.prototype)//true

可以通过__proto__找到say方法


二、原型链

QQ图片20211105121221.png

JS原型链查找机制

当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾null



活动打卡代码 LeetCode 371. 两整数之和

ZJ.cao
2个月前
class Solution {
    public int getSum(int a, int b) {
        if(a == 0) return b;
        if(b == 0) return a;
        int sum = a ^ b;
        int carry = (a & b) << 1;
        return getSum(sum, carry);
    }
}


活动打卡代码 AcWing 38. 外观数列

ZJ.cao
2个月前

双指针

class Solution {
    public String countAndSay(int n) {
        StringBuilder ans = new StringBuilder("1");
        for(int i = 1; i <= n-1; i ++){
            StringBuilder t = new StringBuilder("");
            for(int j = 0; j < ans.length(); j ++){
                int k = j;
                while(k < ans.length() && ans.charAt(k) == ans.charAt(j))  ++k;
                t.append(k-j).append(ans.charAt(j));
                j = k-1;
            }
            ans = t;
        }
        return ans.toString();
    }
}