profile
viewpoint
司徒正美 RubyLouvre qunar.com China http://www.cnblogs.com/rubylouvre/ 穿梭于二进制与二次元的JS魔术师

RubyLouvre/avalon 5497

an elegant efficient express mvvm framework

RubyLouvre/anu 2918

the React16-compat library with hooks

RubyLouvre/avalon.oniui 425

基于avalon的组件库

RubyLouvre/agate 74

灵活易用的nodejs后端框架

RubyLouvre/avalon.bootstrap 40

基于avalon的bootstrap

RubyLouvre/avalon.test 31

专门用于放置avalon的单元测试

RubyLouvre/algorithmbook 28

没有经过整理的知识才是徒然浪费时间,伤透脑筋!

RubyLouvre/avalon-server-render-example 27

avalon2+koa2的后端渲染例子

RubyLouvre/create-anu-app 27

anujs的官方脚手架

RubyLouvre/anu-ie8-example 17

anu运行在IE8的例子

startedDangoSky/algorithm

started time in 2 days

issue openedRubyLouvre/algorithmbook

表达式求值

表达式求值

表达式求值是程序设计语言中的一个最基本问题。它的实现是栈应用的又一个典型例子。这里介绍一种简单直观、广为使用的算法,通常称为“算符优先法”。

要把一个表达式翻译成正确求值的一个机器指令序列,或者直接对表达式求值,首先要能够正确解释表达式。例如要对下述表达式求值:

4+(6-10+2*2)*2

首先,要了解算术四则运算的规则。即:

  1. 先乘除,后加减;
  2. 从左算到右
  3. 先括号内,后括号外

由此,这个算术表达式的计算顺序应为:

4+(6-10+2*2)2 = 4+(-4+22)*2 = 4+(-4+4)2 = 4+02 = 4+0 = 4 1

任何一个表达式都是由操作数(operand)、运算符(operator)和界限符(delimiter)组成。界限符也就是小括号,运算符包括加减乘除,以及更复杂的求余、三角函数等等。这里我们只讨论比较简单的算术表达式,只包括加减乘除四种运算符。

我们把运算符和界限符统称为算符,根据上述3条运算规则,在运算每一步中,任意两个相继出现的算符θ1和θ2之间的优先关系至多是下面三种关系之一:

  • θ1 < θ2,θ1的优先权低于θ2
  • θ1 = θ2,θ1的优先权等于θ2
  • θ1 > θ2,θ1的优先权大于θ2 下表定义了这种优先关系:

![image_1cjig9ta61iptmic1j4h1qsi18rh1j.png-23.2kB][14]

由规则(3),+、-、*和/为θ1时的优先级均低于“(”但高于右括号”)”,由规则(2),当θ1 = θ2时,令θ1 > θ2。

基于上述的论述,首先,我们来讨论使用算符优先算法来实现表达式的求值。

为实现该算法,我们需要使用两个工作栈。一个称作OPTR,用以寄存运算符;另一个称作OPND,用以寄存操作数或运算结果。算法的基本思想是:

1.首先设置两个栈:操作数栈和操作符栈 2.依次读入表达式中的每个字符,若是操作数则进OPND栈,若是运算符则和OPTR栈的栈顶运算符比较优先权后作相应操作。

1.若该运算符优先权大于栈顶运算符优先权则该运算符直接进OPTR栈;反之若运算符优先权小于栈顶运算符的优先权,则弹出栈顶运算符,并从操作数OPND栈弹出两个数进行该栈顶运算符的运算,运算结果再加入OPND操作数栈。 2.循环往复地进行第1步判断。直到将该操作符加入OPTR操作符栈

3.表达式读取结束,若两个栈都不为空,则依次弹出OPTR栈中的运算符和OPND栈中的两个操作数,进行运算后,将运算结果在加入OPND栈。直到OPTR栈为空,OPND栈只剩下一个元素,则该元素就是运算结果。

4.中间出现差错,比如最后OPND栈剩下不止一个数,则视为表达式出错。

下面是完整代码:

function evaluate(expression) {
    var OPND_stack = new Stack(); // 操作数栈
    var OPTR_stack = new Stack(); // 操作符栈
    // 遍历这个表达式
    for (var i = 0; i < expression.length; i++) {
        var c = expression.charAt(i);
        // 如果当前字符是数字,也就是操作数
        if (isDigit(c) || c == '.') {
            var stringBulider = ""
            // 操作数的拼接,包括小数点
            while (i < expression.length && (isDigit(c = expression.charAt(i)) || c == '.')) {
                stringBulider += c;
                i++;
            }
            // 操作数入栈
            OPND_stack.push(Number(stringBulider));
            // 跳过本次循环,i的值已经增加过,所以要减去
            i--;
            continue;
        } else {
            // 当前的字符是操作符
            outer: while (!OPTR_stack.isEmpty()) {
                switch (precede(OPTR_stack.top(), c)) {
                    case '<':
                        // 栈顶运算符小于该运算符,该运算符直接入栈
                        OPTR_stack.push(c);
                        break outer;
                    case '=':
                        // 栈顶运算符等于该运算符,只有一种情况,左右括号匹配,弹出左括号
                        OPTR_stack.pop();
                        break outer;
                    case '>':
                        // 栈顶运算符大小该运算符
                        var operator = OPTR_stack.pop();
                        // 如果有多余的操作符却没有操作数可以计算了,那么说明表达式错误
                        try {
                            var opnd2 = OPND_stack.pop();
                            var opnd1 = OPND_stack.pop();
                            OPND_stack.push(operate(opnd1, operator, opnd2));
                        } catch (e) {
                            console.log("表达式有误0!");
                            return
                        }
                        break;
                }
            }
            // 第一次栈为空的情况,直接入栈。还有退栈直至栈为空的情况,当前操作符也需要入栈
            if (OPTR_stack.isEmpty()) {
                OPTR_stack.push(c);
            }
        }
    }
    while (!OPTR_stack.isEmpty()) {
        var optr = OPTR_stack.pop();
        // 如果有多余的操作符却没有操作数可以计算了,那么说明表达式错误
        try {
            var opnd2 = OPND_stack.pop();
            var opnd1 = OPND_stack.pop();
            OPND_stack.push(operate(opnd1, optr, opnd2));
        } catch (e) {
            console.log("表达式有误!");
            return
        }
    }
    if (OPND_stack.size() == 1) {
        return OPND_stack.pop();
    } else {
        console.log("表达式有误!");
        return
    }
    return 0;
}

function isDigit(c) {
    return /[0-9]/.test(c)
}

function operate(opnd1, optr, opnd2) { //运算
    switch (optr) {
        case '+':
            return opnd1 + opnd2;
        case '-':
            return opnd1 - opnd2;
        case '*':
            return opnd1 * opnd2;
        case '/':
            return opnd1 / opnd2;
    }
    return 0;
}
// 比较两个运算符的优先权大小
function precede(θ1, θ2) {
    if (θ1 == '+' || θ1 == '-') {
        if (θ2 == '+' || θ2 == '-' || θ2 == ')') {
            return '>';
        } else {
            return '<';
        }
    } else if (θ1 == '*' || θ1 == '/') {
        if (θ2 == '(') {
            return '<';
        } else {
            return '>';
        }
    } else if (θ1 == '(') {
        if (θ2 == ')') {
            return '=';
        } else {
            return '<';
        }
    } else if (θ1 == ')') {
        return '>';
    }
    return '>';
}
console.log(evaluate("12*(3+4)-6+8/1"))

created time in 2 days

issue openedRubyLouvre/algorithmbook

散列

3.6 散列

散列又叫哈希表,其实是我们前端人最常用的结构了,因为javascript的对象就是一个散列。在实现链表,我们使用insertAt, 来指定数据放入某个位置上。但这个要遍历内部的结构,即便使用了双向链表,其查找速度还是无法与数组相比拟。但数组也有问题,它是查找容易,插入和删除困难;链表则是查找困难,插入和删除容易。

基于这原因,前辈们通过某种算法将关键字转换成数字,实现O(1)的插入删除与查找,综合上两者优点,这就是散列。

![[图片]][17]

下面是完整的定义

散列法存储的线性表被称为哈希表,使用的函数被称为散列函数或者哈希函数,f(k)被称为散列地址或者哈希地址。通常情况下,散列表的存储空间是一个一维数组,而其哈希地址为数组的下标。散列表中的一个位置称为槽(slot)。

我们的重点是设计哈希函数。

哈希函数的选择原则:

1:若哈希函数是一个一一对应的函数,则在查找时,只需要根据哈希函数对给定关键字的某种运算得到待查找结点的存储位置,无需进行比较

2:一般情况下,散列表的空间要比结点的集合大,虽然浪费了一部分空间但是却提高了查找的效率,散列表空间为m,填入表中结点数为n,则比值n/m成为哈希表的装填因子,一般取0.65~0.9之间

3:哈希函数应当尽量简单,其值域必须在表长的范围之内,尽量不要产生“冲突”(两个关键字得到相同的哈希地址)

以下有这几利方法:

直接地址法:以关键字的某个线性函数值为哈希地址,可以表示为hash(K)=aK+C;优点是不会产生冲突,缺点是空间复杂度可能会较高,适用于元素较少的情况

除留余数法:它是由数据元素关键字除以某个常数所留的余数为哈希地址,该方法计算简单,适用范围广,是经常使用的一种哈希函数,可以表示为:hash(K)=K mod C;

数字分析法:该方法是取数据元素关键字中某些取值较均匀的数字来作为哈希地址的方法,这样可以尽量避免冲突,但是该方法只适合于所有关键字已知的情况,对于想要设计出更加通用的哈希表并不适用

平方求和法:对当前字串转化为Unicode值,并求出这个值的平方,去平方值中间的几位为当前数字的hash值,具体取几位要取决于当前哈希表的大小。

分段求和法:根据当前哈希表的位数把所要插入的数值分成若干段,把若干段进行相加,舍去调最高位结果就是这个值的哈希值。

一个简单哈希函数不做冲突处理的哈希表实现

class Hash {
    constructor() {
        this.table = new Array(1000);
    }
    hash(data) {
        var total = 0;
        for (var i = 0; i < data.length; i++) {
            total += data.charCodeAt(i);
        }
        //把字符串转化为字符用来求和之后进行平方运算
        var s = total * total + ""
        //保留中间2位
        var index = s.charAt(s.length / 2 - 1) * 10 + s.charAt(s.length / 2) * 1
        console.log("Hash Value: " + data + " -> " + index);
        return index;
    }
    insert(key, data) {
        var index = this.hash(key);
        //把取中当做哈希表中索引
        var index = this.hash(key);
        //把取中当做哈希表中索引
        this.table[index] = {
            name: key,
            data: data
        };
    }
    get(key) {
        var index = this.hash(key);
        var node = this.table[index]
        return node && node.data;
    }
    forEach(cb) {
        for (var i = 0; i < this.table.length; i++) {
            var node = this.table[i]
            if (node) {
                cb(node.data, node.name);
            }
        }
    }
}
var someNames = ["David", "Jennifer", "Donnie", "Raymond", "Cynthia", "Mike", "Clayton", "Danny", "Jonathan"];
var hash = new Hash();
for (var i = 0; i < someNames.length; ++i) {
    hash.insert(someNames[i], someNames[i]);
}

hash.forEach(function(el, i) {
    console.log(el, i)
})

![image_1cjipgpcls1r16re1v13mhp1pi96v.png-72.2kB][18]

哈希冲突的解决方案

在构造哈希表时,存在这样的问题:对于两个不同的关键字,通过我们的哈希函数计算哈希地址时却得到了相同的哈希地址,我们将这种现象称为哈希冲突

https://segmentfault.com/img/bV3f92?w=783&h=312![image_1cjin4ncud0q18p41vuc97m1ck165.png-165.5kB][19]

解决冲突的技术可以分为两类:开散列方法(open hashing)和闭散列方法(closed hashing,也称开地址方法,open addressing) 开散列方法解决冲突是将冲突记录在表外,而闭散列方法是将冲突记录在表内的另一个位置上。

拉链法

开散列法最著名的实现是拉链法。它把散列表中的每个槽定义为一个链表的表头。散列到一个特定槽的所有记录都放到这个槽的链表中。我们在添加元素时,通过哈希函数计算出索引值,然后判定它是否为空,不为空则遍历链表是否已经保存相同的值。否则就创建一个新节点,插入到数组上, 原链表则作为跟班挂在它的next属性中。删除时,为了方便,直接将链表的data属性置为null。 ![image_1dgecf55ga9m1b6t1lq1rrq12li3t.png-45.8kB][20]

class Node {
    constructor(name, data) {
        this.name = name;
        this.data = data;
        this.next = null
    }
}
class Hash {
    constructor() {
        this.table = [];
    }
    hash(key) {
        key += ""; //强制转字符串
        var HASHSIZE = 100
        var h = 0
        for (var i = 0; i < key.length; i++) {
            h = key.charCodeAt(i) + h * 31
        }
        //将整个字符串按照特定关系转化为一个整数,然后对hash长度取余
        return h % HASHSIZE;
    }
    loopup(key) {
        var hashvalue = this.hash(key);
        var node = this.table[hashvalue];
        while (node) {
            if (node.name == key + "") {
                return node
            }
            node = node.next
        }
    }
    get(key) {
        var node = this.loopup(key)
        return (node && node.data !== null) ? node.data : null;
    }
    remove(key) {
        var node = this.loopup(key);
        if (node) {
            node.data = null
        }
    }
    insert(key, data) {
        var hashvalue = this.hash(key);
        //头插法,不管该hash位置有没有其他结点,直接插入结点
        var node = this.table[hashvalue]
        var next = node;
        if (node) {
            do {
                if (node.name === key+"") {
                    node.data = value;
                    return //key,data一致
                }
            } while (node = node.next)
        }
        var np = new Node(key, data);
        this.table[hashvalue] = np;
        np.next = next;
    }
    forEach(cb) {
        for (var i = 0; i < 100; i++) {//HASHSIZE = 100
            if (this.table[i]) {
                var link = this.table[i]
                while (link) {
                    if (link.data !== null) {
                        cb(link.name, link.data)
                    }
                    link = link.next
                }
            }
        }
    }
}

var names = ["First Name", "Last Name", "address", "phone", "k101", "k110"];
var descs = ["Kobe", "Bryant", "USA", "26300788", "Value1", "Value2"];
var hash = new Hash()
for (var i = 0; i < 6; ++i) {
    hash.insert(names[i], descs[i]);
}
console.log("we should see ", hash.get("k110"));
hash.insert("phone", "9433120451"); //这里计算的hash是冲突的,为了测试冲突情况下的插入
console.log("we have ", hash.get("k101"), "and", hash.get("phone"));

![image_1cjjfbvl2qus19ea15jo199baid93.png-22kB][21]

闭散列方法可选择的方案则很多了,说明这个方向是对的,因此大家才集中精力研究这个。闭功列方法将所有记录都直接存储在散列表中,可以节约空间。

1、线性探测:当不同的key值通过哈希函数映射到同一散列地址上时,检测当前地址的下一个地址是否可以插入,如果可以的话,就存在当前位置的下一个地址,否则,继续向下一个地址寻找,地址++。

2、二次探测:是针对线性探测的一个改进,线性探测后插入的key值太集中,这样造成key值通过散列函数后还是无法正确的映射到地址上,太集中也会造成查找、删除时的效率低下。因此,通过二次探测的方法,取当前地址加上i^2,可以取到的新的地址就会稍微分散开。

如:此时的散列表长度为10: ![image_1cjjadth118fn191ackrje44147c.png-65.7kB][22]

从使用效果来看,线性探索不如二次索引,因此线性探索最后导致索引值都聚集在一起(这在数学上叫基本聚集primary clustering),数据量大了,测测次数会越来越多。

3、伪随机探查 在伪随机探查中,探查序列中的第 i 个槽是 (h(k) + ri) mod M ,ri是 1 到 M-1 之间的数的随机序列。 所有的插入和检索都使用相同的伪随机序列。

尽管二次探查和伪随机探查能够解决基本聚集问题,然而如果散列函数在某个基槽聚集,依然会保持聚集。这个问题称为二次聚集(secondary clustering) 解决二次聚集问题可以使用双散列方法

双散列方法 双散列方法的形式:

function hash1( key,  i){
    return i*hash2(key);
}

hash2 是第二个哈希函数。

好的双散列实现方法应当保证所有探查序列常数都与表 M 长度互素。 其中一种方法是设置 M 为素数,而h2 返回 1<=h2<=M-1 之间的值。 另外一种方法是给定一个 m 值,设置 M = 2m ,然后让 h2 返回 1 到 2m 之间的一个奇数值。

闭散列方法结论

每个新插入操作产生的额外查找代价将在散列表接近半满时急剧增加。 如果还考虑到访问模式,在理想情况下,记录应当沿着探查序列按照访问频率排序。

//使用二次探索实现的散列 by 司徒正美
class Node {
    constructor(name, data) {
        this.name = name;
        this.data = data;
        this.next = null;
        this.state = true
    }
}
class Hash {
    constructor() {
        this.table = [];
        this.capacity = 100; //容量
        this.length = 0;
    }
    hash(s) {
        //更多常用的hash函数见
        // https://segmentfault.com/a/1190000013132249
        var seed = 131; // 31 131 1313 13131 131313 etc..
        var hash = 0;
        for (var i = 0; i < s.length; i++) {
            hash = s.charCodeAt(i) + hash * seed
        }
        return (hash & 0x7FFFFFFF);
    }
    getHash(key, capacity) {
        return this.hash(key + "") % capacity;
    }
    size() {
        return this.length;
    }
    insert(key, value) {
        var inserted = false
        var index = this.find(key, function(item) {
            item.data = value
            if (!item.state) {
                this.length++;
            }
            inserted = item.state = true;
        })
        if (!inserted) {
            this.table[index] = new Node(key, value)
            this.length++;
        }
        if (this.length * 10 / this.capacity > 6) {
            this.capacity *= 2
        }
        return true;
    }

    find(key, cb) {
        var index = this.getHash(key, this.capacity),
            i = 1,
            table = this.table
        while (table[index]) {
            if (table[index].name === key + "") {
                cb.call(this, table[index]);
            }
            index = index + 2 * i - 1;
            index %= this.capacity;
            i++;
        }
        return index
    }
    get(key) {
        var value = null
        this.find(key, function(item) {
            if (item.state) {
                value = item.data;
            }
        })
        return value
    }
    remove(key) {
        var oldSize = this.length;
        var index = this.find(key, function(item) {
            item.state = false;
            this.length--;
            if (this.length * 10 / this.capacity < 6) {
                this.capacity /= 2
            }
        })
        return this.length !== oldSize;
    }
    forEach(cb) {
        for (var i = 0, n = this.capacity; i < n; i++) {
            var el = this.table[i]
            if (el && el.state) {
                cb(el.name, el.data)
            }
        }
    }
}
var names = ["First Name", "Last Name", "address", "phone", "k101", "k110"];
var descs = ["Kobe", "Bryant", "USA", "26300788", "Value1", "Value2"];
var hash = new Hash()
for (var i = 0; i < 6; ++i) {
    hash.insert(names[i], descs[i]);
}
console.log("we should see ", hash.get("k110"));
hash.insert("phone", "9433120451"); //这里计算的hash是冲突的,为了测试冲突情况下的插入
console.log("we have ", hash.get("k101"), "and", hash.get("phone"));

hash.forEach(function(el, i) {
    console.log(el, i)
})

![image_1cjjf3ig91drttph1js81gt8eq889.png-22.3kB][23]

散列的应用

散列的应用还是蛮多,但通常我们不会使用Hash这样一个类,直接用空对象。javascript对象就是一个性能极佳的散列。

  1. 数组去重

如果数组都是字符串或都是数字,我们可以全部放进去,再for in出来就去重了。

var number = [2,3,4,2,5,6,4,88,1]
var hash = {}
number.forEach(function(el){
   hash["."+el] = el //前面加一点是保证它按添加时的顺序for in出来
})
var ret = []
Object.keys(hash).forEach(function(key){
  ret.push(hash[key])
})

  1. 只出现一次的数字

与上面差不多,不过每次放时记录次数,再for in出来时判定次数是否为1.

var number = [2,3,4,2,5,6,4,88,1]
var hash = {}
number.forEach(function(el){
   if(hash[el] ){
      hash[el].count ++
   }else{
      hash[el] = {
         count: 1,
         data: el
      }
   }
   
})
var ret = []
Object.keys(hash).forEach(function(key){
  if(hash[key].count === 1){
     ret.push(hash[key].data)
  }
})
  1. 两数之和

给定一个数字数组,找到两个数,使得他们的和为一个给定的数值target。 这是leetcode非常著名的题目,如果用暴力法来找,性能很差,我们不妨一个查找,一边存储数据。找到就返回它们俩的索引值

function twoSum(numbers,  target) {
    var hash = new Hash() // 
    for(var i = 0; i < numbers.length; i++){
        var el = numbers[i]
       if(hash.get(el) !== null){
          var index = hash.get(el);
          return [index, i]
       }else{
          hash.insert(target - el, i);//target - el可能在后面找到
       }
    }
}
twoSum([5, 75,25], 100)// 1,2 

有关散列的知识点是很多很碎的,都集中如何设计哈希函数与防冲突上,想进阶的同学可以访问如下网址继续学习。哈希是一种非常友好的结构,使用简单也不是面试重点。

  • https://www.zhihu.com/question/26762707

created time in 2 days

issue openedRubyLouvre/algorithmbook

链表排序

链表排序

最后我们看一下链表排序。排序时,我们不能使用任何访问link[index]的排序算法,因此有如下排序方法入围。

插入排序

将链表分明两部分,有序与未排序,每次从未排序区取得第一个,在有序区中找到适合位置进行插入

function insertSort(list) {
    let head = list.head;
    //如果没有或只有一个节点,直接返回
    if (!head || !head.next){
        return;
    } 
    let lastSorted = head;//排好序的最后一个
    while (lastSorted.next) {//如果还有下一个
        let firstUnsort = lastSorted.next;//没有排好序的
        if (lastSorted.val > firstUnsort.val) {
            //排好序的最前一个
            let firstSorted = head, prev = null
            //将firstUnsort移除出来
            lastSorted.next = firstUnsort.next
            //求出firstUnsort的插入位置, 让它在有序区中逐一比较
            while (firstSorted.val < firstUnsort.val) {
                prev = firstSorted
                firstSorted = firstSorted.next
            }
            if (!prev) {//如果firstUnsort是最小,那么prev为null, 
                //它将成为新的head, 并且旧的head充当它的next
                firstUnsort.next = head
                head = firstUnsort
            } else {
                prev.next = firstUnsort;
                firstUnsort.next = firstSorted;
            }
        } else {
            //firstUnsort刚好比lastSorted大
            lastSorted = lastSorted.next;
        }
    }
     //修正首尾节点
    list.head = head;
    list.tail = lastSorted
};

var list = new List()
var array = [2, 3, 8, 7, 4, 5, 9, 6, 1, 0]
array.forEach(function(el, i) {
    list.insertAt(i, el)
})
list.forEach(function(el, i) {
    console.log(i, el)
})
insertSort(list)
console.log("----sorted----", list)
list.forEach(function(el, i) {
    console.log(i, el)
})

![image_1d7f24p6a17b9vbr1e18ctk1q3f9.png-22kB][11]

冒泡排序

左右结节进行比较交换,并且记录最后的结节,收窄比较的范围

function bubbleSort (list) {
  var head = list.head
  if (!head || !head.next) { // 只有一个或0个节点,不用排序
    return
  }
  var smallest = new Node(Number.MIN_VALUE)
  smallest.next = head;
  list.tail = null; //准备重置tail
  var len = 0,  h = smallest;
  while(h){
    len++
    h = h.next
  }
  for (var i = 0; i < len; i++) {//优化1
    var hasSort = true
    h = smallest
    p1 = h.next
    p2 = p1.next
    for (var j = 0; j < len && p2; j++) {//优化2
      if (p1.data > p2.data) {
        h.next = p2
        p1.next = p2.next
        p2.next = p1
        hasSort = false
      }
      h = h.next
      p1 = h.next
      p2 = p1.next
    }
    // 第一次冒泡结束后,p1的数据域最大,即为tail(p2已是null)
    if (!list.tail) { 
      list.tail = p1
    }
    if (hasSort) {
      break
    }
  }
  // 重置新的head
  list.head = smallest.next
}

我们可以回顾之前学到的冒泡优化,可以减少循环次数,如在优化1处,将i = 0改成i = 1;优化2处,则可以将j < len && p2 改成j < len - 1

我们还可以继续优化,引入swapPos变量,减少内循环次数。

function bubbleSort (list) {
  //略....
  var k = len - 1,swapPos = 0
  for (var i = 1; i < len; i++) {
    //略....
    for (var j = 0; j < k; j++) {//k是可变的
      if (p1.data > p2.data) {
        //略....
        hasSort = false
        swapPos = j;
      }
      //略....
    }
    //略....
    k = swapPos
  }
  // 重置新的head
  list.head = smallest.next
}

选择排序

与插入排序一样,分为两个区,但它是每次从无序序区找到最小的节点,插入到有序区的最后

function selectSort (list) {
  var head = list.head
  if (!head || !head.next) {
    return
  }
  var firstSorted, lastSorted, minPrev, min, p
  while (head){
    // 1. 在链表中找到数据域最小的节点。
    for (p = head, min = head; p.next; p = p.next) {
      if (p.next.val < min.val) {
        minPrev = p
        min = p.next
      }
    }
    // 2. 构建有序链表
    if (!firstSorted) {
      firstSorted = min; // 如果目前还是一个空链表,那么设置 firstSorted
    } else {
      lastSorted.next = min; // 否则直接将min加在有序链表的末端 
    }
    // 3. 调整lastSorted
    lastSorted = min
    // 4. 将min从原链表中移除
    if (min == head) { // 如果找到的最小节点就是第一个节点
      head = head.next; // 显然让head指向原head.next,即第二个节点,就OK
    }  else {
      minPrev.next = min.next; // 移除
    }
  }
  if (lastSorted) {
    lastSorted.next = null; // 清空有序链表的最后节点的next引用
  }
  list.head = firstSorted
  list.tail = lastSorted
}

快速排序

快排的核心是partition,我们选取第一个节点作为枢纽元,然后把小于枢纽的节点放到一个链中,把不小于枢纽的及节点放到另一个链中,最后把两条链以及枢纽连接成一条链。

 function quickSort (list) {
  var head = list.head
  if (!head || !head.next) {
    return
  }
  var tempHead = new Node(0)
  tempHead.next = head
  recursion(tempHead, head, null)
  var h = list.head = tempHead.next
  while(h){
    list.tail = h
    h = h.next
  }
}
function recursion (prevHead, head, tail) {
  // 链表范围是[low, high)
  if (head != tail && head.next != tail) {
    var mid = partition(prevHead, head, tail); // 注意这里head可能不再指向链表头了
    recursion(prevHead, prevHead.next, mid)
    recursion(mid, mid.next, tail)
  }
}
function partition (prevLow, low, high) {
  // 链表范围是[low, high)
  var pivotkey = low.data; // low作为枢轴
  var little = new Node('')
  var bigger = new Node('')
  var littleHead = little; // 保存原来的引用
  var biggerHead = bigger; // 保存原来的引用
  for (var node = low.next; node != high; node = node.next) {
    if (node.data < pivotkey) {
      little.next = node
      little = node
    } else {
      bigger.next = node
      bigger = node
    }
  }
  // [  prevLow litterNode  ... low  biggerHead ....  big, high   ]
  bigger.next = high
  little.next = low
  low.next = biggerHead.next; // 去掉biggerHead
  prevLow.next = littleHead.next; // 去掉littleHead
  return low
}
//======

function quicksort(head){
    if(!head || !head.next){
        return head;
    }
    var prevHead = new LinkNode(0)
    prevHead.next = head
    quicksort(prevHead, null)
    return prevHead.next
}

function recursion(start, end){
    if (start.next !== end){
        var [prevPivot, pivot] = partition(start, end)
        recursion(start, prevPivot)
        recursion(pivot, end)
    }
}

function partition(prevHead, end){//start一开始是tempHead, end为null
    var second = prevHead.next.next;//第二个元素
    var prevPivot = prevHead.next;//第一个元素
    prevPivot.next = end //将第二个元素移出来
    pivot = prevPivot;//prevPivot
    //[prevHead, .... prevPivot, pivot, ....end]
    while( second != end ){
        var next = second.next
        if (second.val >= prevPivot.val){
            //如果第二个元素大于第一个元素,第一个元素为prevPivot
            //那么将它发配到pivot的右侧   
            //pivot -> second->  pivot.next
            second.next = pivot.next
            pivot.next = second
            if(second.val == prevPivot.val){
                pivot = pivot.next
            }
        } else if (second.val < prevPivot.val){
             //那么将它发配到prevPivot的左侧,prevHead的右侧
            //  prevHead -> second->  prevHead.next
            second.next = prevHead.next
            prevHead.next = second
        } 
        second = next
    }
    return [prevPivot, pivot]
}

created time in 2 days

issue commentRubyLouvre/algorithmbook

排序

归并排序更好的图示 https://blog.csdn.net/zhuzuwei/article/details/80603708

RubyLouvre

comment created time in 2 days

push eventRubyLouvre/anu

司徒正美

commit sha b99d90b707214093e3bf61a6e8ba269d0d1043d5

Update readme.md update

view details

push time in 2 days

issue commentRubyLouvre/algorithmbook

排序

快排

 function swap(array, a, b) {
            var temp = array[a];
            array[a] = array[b];
            array[b] = temp;
        }
        function quickSort(array) {
            function QuickSort(array, left, right) {
                if (left < right) {
                    var index = partition3(array, left, right);
                    QuickSort(array, left, index - 1);
                    QuickSort(array, index + 1, right);
                }
            }
            QuickSort(array, 0, array.length - 1);
            return array
        }

        function partition(array, left, right) {//分治函数
            var pivot = array[right];
            var pivotIndex = right;
            while (left < right) {
                while (left < right && array[left] <= pivot) {
                    // 1.  防止越界需要left < right
                    // 2. array[left] <= pivot 因为可能存在相同元素,
                    left++; //找到比pivot大
                }
                while (left < right && array[right] >= pivot) {
                    right--; //找到比pivot小
                }
                swap(array, left, right);
            }
            //最后一个比pivot大的left元素要与pivot相交换
            swap(array, left, pivotIndex);
            return left; //返回的是中间的位置
        }
        function partition2(array, left, right) {//分治函数
            var pivot = array[right];
            var pivotIndex = right;
            while (left < right) {
                while (left < right && array[left] <= pivot) {
                    // 1.  防止越界需要left < right
                    // 2. array[left] <= pivot 因为可能存在相同元素,
                    left++; //找到比pivot大
                }
                array[right] = array[left]
                while (left < right && array[right] >= pivot) {
                    right--; //找到比pivot小
                }
                array[left] = array[right]
            }
            //最后一个比pivot大的left元素要与pivot相交换
            array[right] = pivot
            return right; //返回的是中间的位置
        }

        function partition3(arr, left, right) {
            var cur = left; //找大数
            var prev = cur - 1; //找小数
            var key = arr[right];
            while (cur <= right) {
                if (arr[cur] <= key && ++prev != cur)
                    swap(arr, prev, cur);
                cur++;
            }
            return prev;
        }
        console.log(quickSort([4, 1, 7, 6, 9, 2, 8, 0, 3, 5]))
        console.log(quickSort([1, 0, 3, 1, 0, 1, 1]))
        console.log(quickSort([0, 5, 3, 2, 2]))
        console.log(quickSort([-2, -5, -45]))
RubyLouvre

comment created time in 3 days

issue commentRubyLouvre/algorithmbook

排序

计数排序

function countSort(arr) {
    var max = arr[0], min = arr[0], n = arr.length;
    for (var i = 0; i < n; i++) {
        if (arr[i] > max) {
            max = arr[i];
        }
        if (arr[i] < min) {
            min = arr[i];
        }
    }
    var size = max - min + 1;
    var buckets = new Array(size).fill(0);
    //遍历所有桶
    for (var i = 0; i < n; i++) {
        buckets[arr[i] - min]++
    }
    for (var i = 1; i < size; i++) {
        //求前缀和
        buckets[i] += buckets[i - 1];
    }
    var ret = [];//逆向遍历源数组(保证稳定性)
    for (var i = n - 1; i >= 0; i--) {
        buckets[arr[i] - min]--;
        ret[buckets[arr[i] - min]] = arr[i];
    }
    return ret;
}

console.log(countSort([1, 0, 3, 1, 0, 1, 1]))
console.log(countSort([0, 5, 3, 2, 2]))
console.log(countSort([-2, -5, -45]))
RubyLouvre

comment created time in 3 days

issue commentRubyLouvre/algorithmbook

排序

最大组合数问题

给一个非负整数数组,让它排序后合并后得到的数字最大,比如[3, 30, 34, 5, 9]排序成[9, 5, 34, 3, 30],得到的数9534330为最大。

思路:我们先比较相邻两个数,它们组合后的两个方式的大小,

 [3, 30, 34, 5, 9].
        sort(function(a, b) {
            var v1 = Number(a + "" + b)
            var v2 = Number(b + "" + a);
            var ret = v1 > v2 ? 1 : (v1 === v2 ? 0: -1)
            return -1 * ret;
        })
RubyLouvre

comment created time in 3 days

issue commentRubyLouvre/algorithmbook

排序

三路快排

快排是二路划分的算法。如果待排序列中重复元素过多,也会大大影响排序的性能。这时候,如果采用三路划分,则会很好的避免这个问题。

https://blog.csdn.net/lw_power/article/details/77986602 https://blog.csdn.net/jlqCloud/article/details/46939703

function quickSort3Ways(arr, left, right) {
    if (left >= right) {
        return;
    }

    var lt = left;
    var gt = right;
    var i = left + 1;
    var pivot = arr[left];
    while (i <= gt) {
        if (arr[i] < pivot) {
            swap(arr, i++, lt++);

        } else if (arr[i] > pivot) {
            swap(arr, i, gt--);
        } else { // arr[i]==v
            i++;
        }
    }
    quickSort3Ways(arr, left, lt - 1);
    quickSort3Ways(arr, gt + 1, right);

}

function quick(a) {
    if (a.length > 0) {
        quickSort3Ways(a, 0, a.length - 1);
    }
}
//4 1 3 0 2 5 9 8 6 7
var array = [4, 1, 7, 6, 9, 2, 8, 0, 3, 5]
quick(array)
console.log(array)

双基准快速排序

与上面的三路快排功率差不多,它也是用来改善数组重复元素够多的情况

//inspired by https://blog.csdn.net/limenglin0927/article/details/18077923
function quickSortDualPivot(array, left, right) {
    if (right <= left) return;

    var pivot1 = array[left];
    var pivot2 = array[right];

    if (pivot1 > pivot2) {
        swap(array, left, right);
        pivot1 = array[left];
        pivot2 = array[right];
        //sort(array, left, right);
    } else if (pivot1 == pivot2) {
        while (pivot1 == pivot2 && left < right) {
            left++;
            pivot1 = array[left];
        }
    }

    var i = left + 1;
    var lt = left + 1;
    var gt = right - 1;

    while (i <= gt) {

        if (array[i] < pivot1) {
            swap(array, i++, lt++);
        } else if (pivot2 < array[i]) {
            swap(array, i, gt--);
        } else {
            i++;
        }

    }

    swap(array, left, --lt);
    swap(array, right, ++gt);
    quickSortDualPivot(array, left, lt - 1);
    quickSortDualPivot(array, lt + 1, gt - 1);
    quickSortDualPivot(array, gt + 1, right);
}

function quick(a) {
    if (a.length > 0) {
        quickSortDualPivot(a, 0, a.length - 1);
    }
}
//4 1 3 0 2 5 9 8 6 7
var array = [4, 1, 1, 7, 6, 9, 5, 2, 8, 0, 3, 5]
quick(array)
console.log(array)
RubyLouvre

comment created time in 3 days

issue commentRubyLouvre/algorithmbook

排序

刚才我们是从上到下进行归产排序,我们的思路总是想着左边要合并右边。如果们一开始就把数组的每一个元素都当成一个微型数组,然后两两合并,再继而四四合并,一直它的长度靠近原数组长度。这样排序就完成了。

image


function mergeArray(a, first, mid, last, temp) {
  var i = first, j = mid + 1;
  var m = mid, n = last;
  var k = 0;
  while (i <= m && j <= n) {
    if (a[i] <= a[j]) {
      temp[k++] = a[i++];
    } else {
      temp[k++] = a[j++];
    }
  }
  while (i <= m) {
    temp[k++] = a[i++];
  }
  while (j <= n) {
    temp[k++] = a[j++];
  }
  for (i = 0; i < k; i++) {
    a[first + i] = temp[i];
  }
}
function mergeSort(array) {// 进行两两归并
  var n = array.length;
  var temp = new Array(n)// 一次性的分配辅助空间
    //定义微型数组的长度,初始为1
  for (var sz = 1; sz < n; sz = sz + sz) {
    //定义微型数组的索引low
    for (var low = 0; low < n - sz; low += sz + sz) {
      mergeArray(array, low, low + sz - 1, 
         Math.min(low + sz + sz - 1, n - 1), temp);
    }
  }
}

RubyLouvre

comment created time in 3 days

issue commentRubyLouvre/algorithmbook

排序

归并排序

function mergeArray(a, b) {
    //n, m分别为a,b的最后索引; i为a的索引,j为b的索引,k为c的索引
    var n = a.length - 1, m = b.length - 1, i = 0, j = 0, k = 0, c = []
    while (i <= n && j <= m) {
        //先比较两个数组等长的部分,看谁的元素较小,谁就先进c数组
        c[k++] = a[i] < b[j] ? a[i++] : b[j++];
    }
    //可能a数组长些,那么将a数组剩下的元素一古脑儿全部扔进去
    while (i <= n) {
        c[k++] = a[i++];
    }
    //也可能是b数组长些,那么b数组的剩下的元素扔进去
    while (j <= m) {
        c[k++] = b[j++];
    }
    return c
}
function mergeSort(array, toMerge) {
    //如果数组还可以分割,并且处于分割模式
    if (array.length > 1 && toMerge !== true) {
        var top = array;
        var mid = array.length >> 1;
        top.left = array.slice(0, mid)
        top.right = array.slice(mid);
        top.left.top = top
        top.right.top = top;
        console.log(top.left, top.right, "分割")
        mergeSort(top.left)
        mergeSort(top.right)
        //如果数组只剩下一个或者处于合并模式
    } else if (array.length === 1 || toMerge) {
        if (array.top && !array.merged) { //如果左边合并了右边,那么右边就不用再合并左边
            var isLeft = array === array.top.left;
            var neighbor = isLeft ? array.top.right : array.top.left;
            if (neighbor.length === 1 || neighbor.sorted) {
                var temp = mergeArray(array, neighbor)
                neighbor.merged = true;//表明已经
                console.log(temp, "合并")
                for (var i = 0, n = temp.length; i < n; i++) {
                    array.top[i] = temp[i]
                }
                array.top.sorted = true
                mergeSort(array.top, true)
            }
        }
    }
}

var array = [3, 4, 9, 1, 8, 2, 0, 7, 6, 5]
mergeSort(array)
console.log(array.concat())


function mergeSort2(obj, toMerge) {
    //如果数组还可以分割,并且处于分割模式
    var { array, begin, end } = obj;
    var n = end - begin;
    if (n !== 0 && toMerge !== true) {
        var mid = begin + ((end - begin) >> 1);
        obj.left = {
            begin: begin,
            end: mid,
            array: array,
            top: obj,
        }
        obj.right = {
            begin: mid + 1,
            end: end,
            array: array,
            top: obj,
        }
        mergeSort2(obj.left)
        mergeSort2(obj.right)
        //如果数组只剩下一个或者处于合并模式
    } else if (n === 0 || toMerge) {
        if (obj.top && !obj.merged) { //如果左边合并了右边,那么右边就不用再合并左边
            var top = obj.top;
            var isLeft = obj === top.left;
            var neighbor = isLeft ? top.right : top.left;
            if ((neighbor.end == neighbor.begin) || neighbor.sorted) {
                var temp = mergeArray2(array, begin, end, neighbor.begin, neighbor.end)
                neighbor.merged = true;//表明已经
                var b = top.begin;
                for (var i = 0, n = temp.length; i < n; i++) {
                    array[b + i] = temp[i]
                }
                top.sorted = true
                mergeSort2(top, true)
            }
        }
    }
}
function mergeArray2(a, begin, end, begin2, end2) {
    //n, m分别为a,b的最后索引; i为a的索引,j为b的索引,k为c的索引
    var n = end, m = end2, i = begin, j = begin2, k = 0, c = []
    while (i <= n && j <= m) {
        //先比较两个数组等长的部分,看谁的元素较先,谁就先进c数组
        c[k++] = a[i] < a[j] ? a[i++] : a[j++];
    }
    //可能a数组长些,那么将a数组剩下的元素一古脑儿全部扔进去
    while (i <= n) {
        c[k++] = a[i++];
    }
    //也可能是b数组长些,那么b数组的剩下的元素扔进去
    while (j <= m) {
        c[k++] = a[j++];
    }
    return c
}
var array = [3, 4, 9, 1, 8, 2, 0, 7, 6, 5]
mergeSort2({
    array: array,
    begin: 0,
    end: array.length - 1
})
console.log(array)

RubyLouvre

comment created time in 3 days

issue commentRubyLouvre/algorithmbook

排序

希尔排序


function shellSort(array) {
    //生成增量序列 3x+1 [1, 4, 13, 40, 121, 364, 1093, 3280, 9841] 
    var n = array.length,
        gaps = [1],
        gap = 1;
    while (true) {
        gap = gap * 3 + 1
        if (gap >= n) { //不能大于数组长度
            break
        }
        gaps.push(gap)
    }
    while (gap = gaps.pop()) {
        //对每个子数组进行排序
        for (var g = 0; g < gap; g++) {
            //****************正常的插入排序***************
            for (var i = g + gap; i < n; i += gap) {
                var target = array[i]; //从无序区取元素
                if (target < array[i - gap]) {
                    //无序区的元素比有序区的小
                    var j = i;
                    while (j > 0 && array[j - gap] > target) {
                        array[j] = array[j - gap]; //将前面的元素覆盖后面的
                        j -= gap;//不是-1而是-gap
                    }
                    array[j] = target;
                }
            }
            //****************正常的插入排序***************
        }
    }
};

function shellSort2(array) {
    //希尔序列 [1, 2, 4, 9, 19, 39, 78, 156, 312, 625, 1250, 2500, 5000] 
    var n = array.length,
        gaps = [],
        gap = n;
    while (gap != 1) {
        gap = gap >> 1; //相当于 Math.floor(n/2)
        gaps.unshift(gap)
    }
    while (gap = gaps.pop()) {
        //对每个子数组进行排序
        for (var g = 0; g < gap; g++) {
            //****************正常的插入排序***************
            for (var i = g + gap; i < n; i += gap) {
                var target = array[i]; //从无序区取元素
                if (target < array[i - gap]) {
                    //无序区的元素比有序区的小
                    var j = i;
                    while (j > 0 && array[j - gap] > target) {
                        array[j] = array[j - gap]; //将前面的元素覆盖后面的
                        j -= gap;//不是-1而是-gap
                    }
                    array[j] = target;
                }
            }
            //****************正常的插入排序***************
        }
    }
};
function getSedgewickSeq(n) {
    var startup1 = 0, startup2 = 2, array = [];
    for (var i = 0; i < n; i++) {
        if (i % 2 == 0) {
            array[i] = 9 * Math.pow(4, startup1) - 9 * Math.pow(2, startup1) + 1;
            startup1++;
        } else {
            array[i] = Math.pow(4, startup2) - 3 * Math.pow(2, startup2) + 1;
            startup2++;
        }
        if (array[i] >= n) {
            break;
        }
    }
    return array
}

function shellSort3(array) {
    //生成增量序列 [1, 5, 19, 41, 109, 209, 505, 929, 2161, 3905, 8929, 16001] 
    var n = array.length,
        gaps = getSedgewickSeq(n),
        gap = 1;
    while (gap = gaps.pop()) {
        //对每个子数组进行排序
        for (var g = 0; g < gap; g++) {
            //****************正常的插入排序***************
            for (var i = g + gap; i < n; i += gap) {
                var target = array[i]; //从无序区取元素
                if (target < array[i - gap]) {
                    //无序区的元素比有序区的小
                    var j = i;
                    while (j > 0 && array[j - gap] > target) {
                        array[j] = array[j - gap]; //将前面的元素覆盖后面的
                        j -= gap;//不是-1而是-gap
                    }
                    array[j] = target;
                }
            }
            //****************正常的插入排序***************
        }
    }
}

test(shellSort)
test(shellSort2)
test(shellSort3)

RubyLouvre

comment created time in 3 days

issue commentRubyLouvre/algorithmbook

排序

插入排序

function insertSort2(array) {
    var n = array.length
    for (var i = 1; i < n; i++) { //[i,n-1]是无序区
        var target = array[i];
        if (target < array[i - 1]) { //减少无效的内部循环
            var j = i;
            while (j > 0 && array[j - 1] > target) {
                array[j] = array[j - 1]; // 前面的覆盖后面的
                j--;
            }
            array[j] = target; //放入坑位
        }
    }
}
RubyLouvre

comment created time in 3 days

issue commentRubyLouvre/algorithmbook

排序

选择排序

function selectSort(array) {
  var n = array.length;
  for (var i = 0; i < n; i++) {
    var minIndex = i; //保存当前最小数的索引
    for (var j = i + 1; j < n; j++) { //每次只从i的后一个位置开始查找
      if (array[j] < array[minIndex]) {
        minIndex = j;   
      }
    }
    if (i !== minIndex) {
      swap(array, i, minIndex)
    }
  }
}
RubyLouvre

comment created time in 4 days

issue openedRubyLouvre/algorithmbook

排序

冒泡排序

//这个方法非常常用,其他章节都会用到,以后就省略不写
function swap(array, a, b) {
    var temp = array[a];
    array[a] = array[b];
    array[b] = temp;
}


function bubbleSort1(array) {
    var n = array.length
    for (var i = 1; i < n; i++) {
        for (var j = 0; j < n - 1; j++) {
            if (array[j] > array[j + 1]) { //注意这里的索引变量都是j
                swap(array, j, j + 1)
            }
        }
    }
}

function bubbleSort2(array) {
    var n = array.length;
    for (var i = 1; i < n; i++) {
        var hasSort = true;
        for (var j = 0; j < n - 1; j++) {
            if (array[j] > array[j + 1]) { //注意这里的索引变量都是j
                swap(array, j, j + 1);
                hasSort = false
            }
        }
        if (hasSort) {
            break;
        }
    }
}
function bubbleSort3(array) {
    var n = array.length, k = n - 1, swapPos = 0;
    for (var i = 1; i < n; i++) {
        var hasSort = true;
        for (var j = 0; j < k; j++) {
            if (array[j] > array[j + 1]) { //注意这里的索引变量都是j
                swap(array, j, j + 1);
                hasSort = false;
                swapPos = j; //记录交换位置,直接到内部循环最后一个被交换的元素
            }
        }
        if (hasSort) {
            break;
        }
        k = swapPos;//重写内部循环的最后边界
    }
}
function cocktailSort(array) {
    var left, right, index, i;
    left = 0;//数组起始索引
    right = array.length - 1;//数组索引最大值
    index = left//临时变量

    //判断数组中是否有多个元素
    while (right > left) {
        var isSorted = false;
        //每一次进入while循环都会找出相应范围内最大最小的元素并分别放到相应的位置
        //大的排到后面
        for (i = left; i < right; i++) {//从左向右扫描
            if (array[i] > array[i + 1]) {
                swap(array, i, i + 1);
                index = i;//记录当前索引
                isSorted = true
            }
        }
        right = index;//记录最后一个交换的位置
        //小的放到前面
        for (i = right; i > left; i--) {//从最后一个交换位置从右往左扫描
            if (array[i] < array[i - 1]) {
                swap(array, i, i - 1);
                index = i;
                isSorted = true
            }
        }
        left = index;//记录最后一个交换的位置
        if (!isSorted) {
            break
        }
    }
}
function shuffle(a) {
    var len = a.length;
    for (var i = 0; i < len - 1; i++) {
        var index = parseInt(Math.random() * (len - i));
        var temp = a[index];
        a[index] = a[len - i - 1];
        a[len - i - 1] = temp;
    }
}
function test(sortFn) {
    var array = []
    //向数组写入10000个数据 前1000倒序 , 后9000顺序。
    for (var i = 0; i < 10000; i++) {
        if (i <= 1000) {
            array[i] = 1000 - i;
        } else {
            array[i] = i;
        }
    }
    console.log("========")
    var start = new Date - 0;
    sortFn(array);
    console.log("部分有序的情况", sortFn.name, new Date - start)
    shuffle(array);
    start = new Date - 0;
    sortFn(array);
    console.log("完全乱序的情况", sortFn.name, new Date - start)
}

test(bubbleSort1)
test(bubbleSort2)
test(bubbleSort3)
test(cocktailSort)

image

created time in 4 days

startedevanw/esbuild

started time in 4 days

push eventRubyLouvre/anu

rubylouvre

commit sha 86911d21feada7ddacb603654853fc0d3aa522a3

去掉 nanachi

view details

push time in 14 days

push eventRubyLouvre/anu

rubylouvre

commit sha 5ab5131a7ca0501fc8d8ccef6eca13e4ba698460

移除cli

view details

push time in 14 days

push eventRubyLouvre/anu

rubylouvre

commit sha dab5384d1bdec53e24752adec73f3f348fdce7c9

移除CLI

view details

rubylouvre

commit sha 91686595a1bb66a2455d2727a8ed83234b04b869

Merge branch 'branch3' of github.com:RubyLouvre/anu into branch3 # Conflicts: # index2.html # packages/cli/CHANGELOG.md # packages/cli/bin/cliBuilder.d.ts # packages/cli/bin/commands/build.d.ts # packages/cli/bin/commands/build.js # packages/cli/bin/commands/install.js # packages/cli/bin/index.js # packages/cli/config/h5/webpack.config.js # packages/cli/config/webpackConfig.js # packages/cli/index.js # packages/cli/lib/ReactH5.js # packages/cli/lib/ReactQuick.js # packages/cli/lib/ReactWX.js # packages/cli/nanachi-loader/chaika-plugin/chaikaPlugin.js # packages/cli/nanachi-loader/loaders/nodeLoader.js # packages/cli/package.json # packages/cli/packages/aliHelpers/nodeName.js # packages/cli/packages/babelPlugins/h5/transformH5.js # packages/cli/packages/babelPlugins/h5/transformH5App.js # packages/cli/packages/babelPlugins/miniappVisitor.js # packages/cli/packages/babelPlugins/transformEnv.js # packages/cli/packages/buHelpers/nodeName.js # packages/cli/packages/h5Helpers/components/Picker/DatePickerItem/index.js # packages/cli/packages/h5Helpers/components/Picker/PickerItem/index.js # packages/cli/packages/h5Helpers/components/ScrollView/index.js # packages/cli/packages/h5Helpers/components/TitleBar/index.scss # packages/cli/packages/quickHelpers/PageWrapper.ux # packages/cli/packages/quickHelpers/attrName.js # packages/cli/packages/quickHelpers/config.js # packages/cli/packages/quickHelpers/ignoreAttri.js # packages/cli/packages/quickHelpers/mergeUx.js # packages/cli/packages/quickHelpers/nodeName.js # packages/cli/packages/ttHelpers/nodeName.d.ts # packages/cli/packages/ttHelpers/nodeName.js # packages/cli/packages/utils/getSubPackage.js # packages/cli/packages/utils/index.d.ts # packages/cli/packages/utils/index.js # packages/cli/packages/wxHelpers/nodeName.js # packages/cli/parsers/jsParser/H5Parser.js # packages/cli/parsers/jsParser/QuickParser.js # packages/cli/parsers/jsParser/WxParser.js # packages/cli/parsers/styleParser/LessParser.js # packages/cli/parsers/styleParser/SassParser.js # packages/cli/tasks/chaikaMergeTask/copySource.js # packages/cli/tasks/chaikaMergeTask/index.js # packages/cli/tasks/chaikaMergeTask/mergeFiles.js # packages/cli/tasks/pretasks.js # packages/cli/tasks/runBeforeParseTasks.js # packages/cli/templates/qunar/package.json # packages/cli/templates/qunar/source/pages/native/scrollView/index.js # packages/cli/templates/qunar/source/pages/native/scrollView/index.scss # packages/cli/test/ReactWX.js

view details

push time in 14 days

issue commentRubyLouvre/anu

项目是否考虑升级为ts

刚换工作,没有时间弄。你可以提PR

QiuZhiFeng97

comment created time in 16 days

issue commentRubyLouvre/algorithmbook

求和问题

LeetCode 16 3Sum Closest

求最接近给定值的三数之和

Given an array nums of n integers and an integer target, find three integers in nums such that the sum is closest to target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

Example:

Given array nums = [-1, 2, 1, -4], and target = 1.

The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

function threeSumClosest(nums, target) {
    nums.sort((a, b) => a - b);
    var end = nums.length;
    var val = 0, sum = Infinity
    function backtrack(start, n) {
        if (n == 3) {
            if(Math.abs(val - target) < Math.abs(sum - target)){
                sum =  val
            }
        } else {
            for (var i = start; i < nums.length; i++) {
                val += nums[i];
                backtrack(i + 1, n+1)
                val -= nums[i];
            }
        }
    }
    backtrack(0, 0);
    console.log(sum);
    return sum;
}

threeSumClosest([-1, 2, 1 ,-4], 1);
RubyLouvre

comment created time in a month

MemberEvent
MemberEvent

push eventRubyLouvre/anu

chenfx

commit sha 9e0e217de0da63368287b2b6fbc071c546335348

增加对huawei编译文件的配置

view details

chenfx

commit sha 3166179411f89c4630c6395b5ceef37caa605933

更新增加华为快引用的配置文件的处理

view details

chenfx

commit sha 048e1f99edf6a30fdba2389cb7021b54569dafb0

删除引入没用的模块

view details

司徒正美

commit sha 34d686ce6351c25f3596b2a3b2d5a2528cd4cd14

Merge pull request #1212 from chenfaxiang/feature-add-huawei-config-file opt: 增加华为快应用的配置文件 quickConfig.huawei.json 逻辑

view details

push time in 2 months

PR merged RubyLouvre/anu

opt: 增加华为快应用的配置文件 quickConfig.huawei.json 逻辑

增加华为快应用的配置文件 quickConfig.huawei.json 逻辑

+87 -50

0 comment

3 changed files

chenfaxiang

pr closed time in 2 months

issue commentRubyLouvre/algorithmbook

字符串专题

https://segmentfault.com/a/1190000018554989

RubyLouvre

comment created time in 2 months

issue commentRubyLouvre/algorithmbook

字符串专题


    function findWords(board, words) {
      var visited = new Array(board.length).fill(0).map(function (el, i) {
        return new Array(board[0].length).fill(false)
      })
      var root = new TrieNode().buildTrie(words)
      var res = []

      for(var i = 0; i < board.length; i++){
        for(var j = 0; j < board[0].length; j++){
          if(root.next[board[i][j].charCodeAt(0) -97  ] == null){
            continue
          }
          backtrack(root, i, j)
        }
      }


      function backtrack(node, x, y) {
        if (x == board.length || x < 0 || y == board[0].length || y < 0 || visited[x][y]) {
          return;
        }

        var c = board[x][y].charCodeAt(0) - 97
        if(node.next[c] == null){
          return 
        }
        if(node.next[c].word !== null){
          res.push(node.next[c].word );
          node.next[c].word = null
        }

        visited[x][y] = true;
        backtrack(node.next[c], x + 1, y);
        backtrack(node.next[c], x - 1, y);
        backtrack(node.next[c], x, y + 1);
        backtrack(node.next[c], x, y - 1);
        visited[x][y] = false;
      }
      return res;
    }


    var board = [
      ['o', 'a', 'a', 'n'],
      ['e', 't', 'a', 'e'],
      ['i', 'h', 'k', 'r'],
      ['i', 'f', 'l', 'v']
    ]

    class TrieNode {
      constructor(v){
      }
       buildTrie(words) {
            this.root = new TrieNode('');
            var p = this.root
            for (var  word of words) {
                for (var c of word) {
                    if (!p.next[c.charCodeAt(0)-97] ){
                        p.next[c.charCodeAt(0)-97] = new TrieNode(c);
                    }
                    p = p.next[cc.charCodeAt(0)-97];
                }
                p.word = word;
            }
            return this.root;
        }
    }
  

RubyLouvre

comment created time in 2 months

issue commentRubyLouvre/algorithmbook

回溯问题

找字符串

leetcode 212
Given a 2D board and a list of words from the dictionary, find all words in the board.

Each word must be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once in a word.

function findWords(board, words) {
      var visited = new Array(board.length).fill(0).map(function (el, i) {
        return new Array(board[0].length).fill(false)
      })
      var res = []
      var set = new Set();
      for (var word of words) {
        set.add(word);
      }

      function backtrack(cur, x, y) {
        if (x == board.length || x < 0 || y == board[0].length || y < 0 || visited[x][y]) {
          return;
        }

        var c = board[x][y];
        if (set.has(cur + c)) {
          res.push(cur + c);
          set.delete(cur + c);
        }
        visited[x][y] = true;
        backtrack(cur + c, x + 1, y);
        backtrack(cur + c, x - 1, y);
        backtrack(cur + c, x, y + 1);
        backtrack(cur + c, x, y - 1);
        visited[x][y] = false;
      }

      for (var i = 0; i < board.length; i++) {
        for (var j = 0; j < board[0].length; j++) {
          backtrack("", i, j);
        }
      }
      return res;
    }


    var board = [
      ['o', 'a', 'a', 'n'],
      ['e', 't', 'a', 'e'],
      ['i', 'h', 'k', 'r'],
      ['i', 'f', 'l', 'v']
    ],
      words = ["oath", "pea", "eat", "rain"]

    console.log(findWords(board, words))
RubyLouvre

comment created time in 2 months

issue commentRubyLouvre/algorithmbook

字符串专题

KMP


//保存的是前缀的起始位置,因此又叫前缀数组,
//又因为它只在失配时才使用,因此又叫失配数组
function getMaxLength(pattern) {
  var table = [0],////只有一个字符肯定不匹配
    i = 1,//最大后缀字符串从1开始 
    j = 0,//前缀的指针
    pLen = pattern.length
  while (i < pLen) {
    if (pattern[i] == pattern[j]) {
      table[i] = j + 1;
      j++;
      i++;
    } else {
      table[i] = 0;
      if (j === 0) {          
        i++;
      } else {
        j = table[j - 1];
      }
     
    }
  }
  return table;
}

    function getMaxLength2(pattern) {
      var len = pattern.length;
      var PMT = [0]
      var i = 1;
      var k = 0;
      while (i < len) {
        if (pattern[i] == pattern[k]) {
          // 如果是连续的,那么k+1
          k++;
          PMT[i] = k;
          i++;
        } else {
          if (k != 0) {
            k = PMT[k - 1];
          } else {
            PMT[i] = 0;
            i++;
          }
        }
      }

      return PMT;
    }
    function getMaxLength3(pattern) {
      var len = pattern.length;
      var table = [0]
      var i = 1;
      var j = 0;
      while (i < len) {
        if (pattern[i] == pattern[j]) {

          table[i] = j + 1;
          j++
          i++;
        } else {
          table[i] = 0;
          if (j == 0) {
          
            i++;
          } else {
            j = table[j - 1];
          }
        }
      }

      return table;
    }



    function indexOf(target, pattern) {
      var pmt = getMaxLength(pattern)
      var i = 0, j = 0;
      var tLen = target.length;
      var pLen = pattern.length;
      while (i < tLen && j < pLen) {
        // console.log("i, j ",i, j , target[i] , pattern[j])
        if (target[i] == pattern[j]) {
          i++;
          j++;

        } else {
          if (j == 0) {
            i++; //如果是target[0] !== pattern[0], 那么i还是需要移动
          } else {
            j = pmt[j - 1];// i不动,j从pmt中取
          }
        }
      }
      return j === pLen ? i - j : -1
    }


    function test(a, b) {
      var c = indexOf(a, b)
      var d = a.indexOf(b);
      // console.log(getMaxLength(b))
      console.log(c, d, c === d)
    }
    test("AAADAABCDAB", "ABCDABD")
    test('aadddaa', 'ddd')
    test("mississippi", "issipi")//-1

    test('acabaabaabcacaabc', 'abaabcac')

    test('bbbbababbbaabbba', 'abb')


RubyLouvre

comment created time in 2 months

push eventRubyLouvre/anu

RubyLouvre

commit sha f2e204cfbad31e662c90f9b2c5ff0b0f74457dee

update

view details

push time in 2 months

push eventRubyLouvre/anu

RubyLouvre

commit sha 76ca90ebcad67ef84226d583c680f3612a01f900

更新模板

view details

RubyLouvre

commit sha 99c63de34a0e2f434f2967aaa738bbdfedd092ea

Merge branch 'branch3' of https://github.com/RubyLouvre/anu into branch3

view details

push time in 2 months

push eventRubyLouvre/nanachi

RubyLouvre

commit sha 0ded785abd440b2b91d767564529dba560bd789f

yyyy

view details

push time in 2 months

startedconcentjs/concent

started time in 2 months

issue commentRubyLouvre/anu

nanachi版本升到最新版,windows系统编译没有反应

1.4.2 这是最新的

litterrain

comment created time in 2 months

issue commentRubyLouvre/anu

请教,应该使用哪个版本的devtools呢

是的 用旧的试试吧

NangeGao

comment created time in 2 months

issue closedRubyLouvre/anu

useEffect函数里有setState会死循环

useEffect(() => { console.log(value) setText(value); }, [value]);

closed time in 3 months

zikkeung

push eventRubyLouvre/anu

rubylouvre

commit sha c34a6e6093510d0319bdfe920fadac37d1642297

update useRef的实现

view details

push time in 3 months

push eventRubyLouvre/anu

rubylouvre

commit sha b5614f161e764cfedc04b3d7ac6be4c16326566e

fix useImperativeHandle

view details

push time in 3 months

issue commentRubyLouvre/anu

useEffect 行为不符合预期

先用这里的试试 https://github.com/RubyLouvre/anu/tree/branch3/dist

menhal

comment created time in 3 months

push eventRubyLouvre/anu

rubylouvre

commit sha eeda5994f7020c58f2604b2b06c7189586374044

更新useMemo, useEffect, useCallback的实现

view details

push time in 3 months

issue commentRubyLouvre/anu

textarea输入汉字不触发change事件

@giligiliduang chrome下可以的

menhal

comment created time in 3 months

push eventRubyLouvre/anu

rubylouvre

commit sha 532aff0e15fed3c4cf6c7c516fd5f6e47d911945

update

view details

rubylouvre

commit sha 7f82b5539b6b879a6c17aadb04efa2327244d6a5

Merge branch 'branch3' of github.com:RubyLouvre/anu into branch3 # Conflicts: # index1.html

view details

push time in 3 months

issue commentRubyLouvre/anu

React.memo是否支持??

支持了

huangxinxia

comment created time in 3 months

issue commentRubyLouvre/anu

useEffect 行为不符合预期

就是说第二参数为空数组时,只会触发一次,如果不为空,那么根据是否变动触发

menhal

comment created time in 3 months

issue commentRubyLouvre/anu

useEffect 行为不符合预期

就是说第二参数为空数组时,只会触发一次,如果不为空,那么根据是否变动触发

menhal

comment created time in 3 months

push eventRubyLouvre/anu

RubyLouvre

commit sha 64c51c56d83474a8ab1adb95a29afba82326f4b7

更新快应用观览与选择图片的功能,更新例子

view details

RubyLouvre

commit sha ef636daa359351e7495e29f23f7402bddfd0d559

Merge branch 'branch3' of https://github.com/RubyLouvre/anu into branch3

view details

push time in 3 months

issue commentRubyLouvre/algorithmbook

动态规划

在走完最后一个房间的时候血量至少要剩下1,因此最后的状态可以当成是初始状态,由后往前依次决定在每一个位置至少要有多少血量,这样一个位置的状态是由其下面一个和和左边一个的较小状态决定 。因此一个基本的状态方程是: dp[i][j] = min(dp[i+1][j], dp[i][j+1]) - dungeon[i][j] 。

但是还有一个条件就是在每一个状态必须血量都要大于1,因此我们还需要一个方程在保证在每一个状态都大于1,即:dp[i][j] = max(dp[i][j], 1); 也就是说虽然当前的血量到最后能够剩下1,但是现在已经低于1了,我们需要为其提升血量维持每一个状态至少都为1。 方案1

function calculateMinimumHP(dungeon) {
    var m = dungeon.length, n = dungeon[0].length
    var dp = new Array(m + 1).fill(0)
    dp.forEach(function (el, i) {
        dp[i] = new Array(n + 1).fill(Infinity)
    });
    //原格子的值是其右边与下面的格子的值决定的,为了防止骑士挂掉,值必须为>=1
    //我们又需要找到右边与下面的格子的值小值,来减去现在的格子的值
    dp[m][n - 1] = 1;
    dp[m - 1][n] = 1;
    for (var i = m - 1; i >= 0; i--) {
        for (var j = n - 1; j >= 0; j--) {
            var val = Math.min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j];
            dp[i][j] = Math.max(val, 1);
        }
    }
    return dp[0][0];
}

方案2

function calculateMinimumHP(dungeon) {
    var m = dungeon.length, n = dungeon[0].length
    var dp = new Array(n + 1).fill(Infinity)

    dp[n - 1] = 1; //最右边
    for (var i = m - 1; i >= 0; i--) {
        for (var j = n - 1; j >= 0; j--) {
            var val = Math.min(dp[j], dp[j + 1]) - dungeon[i][j];
            dp[j] = Math.max(val, 1);
        }
    }
    return dp[0];
}
RubyLouvre

comment created time in 3 months

issue commentRubyLouvre/algorithmbook

动态规划

  1. Combination Sum IV

Given an integer array with all positive numbers and no duplicates, find the number of possible combinations that add up to a positive integer target.

Example:

nums = [1, 2, 3]
target = 4

The possible combination ways are:

(1, 1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 3)
(2, 1, 1)
(2, 2)
(3, 1)

Note that different sequences are counted as different combinations.

Therefore the output is 7.

记dp[i]为用nums中的元素组合成数字i的可能组合个数。将target分解为i 与target-i这两个数字,dp[target]+=dp[target-i](i为nums中的元素).于是从底部开始构建,dp[0]=1(自身可以满足target的元素). 对于之后的给一个值k, 处理方法同target.

function combinationSum4(nums, target) {
    var dp = new Array(target + 1).fill(0)
    dp[0] = 1
    nums.sort((a, b) => a - b)
    for (var i = 1; i <= target; i++) {
        for (var a of nums) {
            if (i >= a){
                 dp[i] += dp[i - a];
            }
        }
    }
    return dp.pop()
}
RubyLouvre

comment created time in 3 months

issue commentRubyLouvre/algorithmbook

动态规划

https://zhuanlan.zhihu.com/p/35707293

RubyLouvre

comment created time in 3 months

issue commentRubyLouvre/algorithmbook

动态规划

凑零钱问题

给你 k 种面值的硬币,面值分别为 c1, c2 ... ck,再给一个总金额 n,问你最少需要几枚硬币凑出这个金额,如果不可能凑出,则回答 -1 。

比如说,k = 3,面值分别为 1,2,5,总金额 n = 11,那么最少需要 3 枚硬币,即 11 = 5 + 5 + 1 。

假设dp[i]表示凑够i元所需要的最少硬币数,一共有n种面值硬币,那么>dp[i]=min(dp[i−coins[0]],dp[i−coins[1]],...dp[i−coins[k])+1,其中coins[k]<=i

dp[0] = 0
dp[1] = 1
dp[2] = min{dp[2-1]}+1
dp[3] = min{dp[3-1],dp[3-2]}+1
dp[4] = min{dp[4-1],dp[4-2]}+1
...
dp[11] = min{ dp[11-1],dp[11-2],dp[11-5]}+1

因此有

function coinChange(coins, amount) {
    var dp = [0]
    for (var i = 1; i <= amount; i++) {  //i表示金额数
        var arr = [Infinity]
        for (let coin of coins) {
            //只有当硬币面额不大于金额数时,才能取该硬币
            if (i >= coin) {
                arr.push(dp[i - coin] + 1)
            }
        }
        dp[i] = Math.min.apply(Math, rr)
    }
    return dp[amount] == Infinity ? -1 : dp[amount]
}

可以优化成

function coinChange(coins, amount) {
            var dp = [0]
            for (var i = 1; i <= amount; i++) {  //i表示金额数
                dp[i] = Infinity
                for (let coin of coins) {
                    //只有当硬币面额不大于金额数时,才能取该硬币
                    if (i >= coin) {
                        dp[i] = Math.min(dp[i] , dp[i - coin] + 1)
                    }
                }
            }
            return dp[amount] == Infinity ? -1 : dp[amount]
 }
RubyLouvre

comment created time in 3 months

issue commentRubyLouvre/algorithmbook

动态规划

斐波那契数列

function fib(n){
    //由之前1个或几个项推导新的
    var dp = new Uint16Array(n+1); //从1开始
    dp[1] = dp[2] = 1;
    for(var i = 3; i <= n; i ++){
        dp[i] = dp[i-1] + dp[i-2]
    }
    return dp[n]
}
RubyLouvre

comment created time in 3 months

issue openedRubyLouvre/algorithmbook

动态规划

leetcode120

var minimumTotal = function(triangle) {
    var n = triangle.length;
    var dp = []
    dp[n-1] = []
    var lastRow = triangle[n-1]
    for(var i = 0; i < n; i++){ //完成其中一行
        dp[n-1][i] = lastRow[i]
    }
    for(var i = n-2; i >=0 ; i--){
        var row = triangle[i];
        dp[i] = []
        for(var j = 0; j < row.length; j++){
            dp[i][j] = Math.min(dp[i+1][j], dp[i+1][j+1] ) + row[j]
        }
    }
    return dp[0][0]
};

created time in 3 months

push eventRubyLouvre/anu

RubyLouvre

commit sha 9e9988e6e9d5f3cacd56f37fbdeacbd8dd1fb93f

add

view details

push time in 3 months

push eventRubyLouvre/nanachi

RubyLouvre

commit sha fe509a8c4e38ff01e0fdf2bf4fedfaeb168d325c

update by 11.15

view details

push time in 3 months

push eventRubyLouvre/nanachi

RubyLouvre

commit sha abe056fa251ac4a440be4dbb3e681b2a1e357a08

xxx

view details

push time in 3 months

issue commentRubyLouvre/anu

百度小程序种3.105.17及以上调试基础库,子组件状态变化,不会触发不渲染更新。

https://github.com/RubyLouvre/anu/tree/branch3/dist

使用这个试试。我们周五会发一版。

thisTom

comment created time in 3 months

push eventRubyLouvre/anu

RubyLouvre

commit sha e8dc3f4afcf74068bee84be39c8322afbaccdd3a

修正微信下多次跳转,小程序没有更新的问题

view details

push time in 3 months

issue closedRubyLouvre/anu

百度智能小程序9月生命周期非兼容性改动

https://smartprogram.baidu.com/forum/topic/show/70128 更新这个改动后,子组件中 应该触发渲染的时候却没有渲染,即使render方法打印出了数据的变化,视图还是没有想要的变化,子使用了componentWillReceiveProps生命周期。 image

closed time in 3 months

thisTom

issue commentRubyLouvre/anu

百度智能小程序9月生命周期非兼容性改动

image

nanachi init aaa
cd aaa && npm i
nanachi watch:bu

将source/pages/syntax/extends/index改成

import React from '@react';
import './index.scss';
import Dog from '@syntaxComponents/Dog/index';

class P extends React.Component {
    state = {
        name: 'ruby'
    }
    render() {
        return (
            <div class="anu-block">
                <div >类继承的演示</div>
                <Dog name={this.state.name} age={12} />
            </div>
        );
    }
    componentWillMount(){
        setTimeout(()=>{
            this.setState({name: 1000})
        }, 3000)
       
    }
}

export default P;

将source/components/Animal/index

  componentWillReceiveProps(props){
        this.setState({
            name: props.name+"1"
        });
    }

没有发现问题

thisTom

comment created time in 4 months

issue commentRubyLouvre/anu

百度智能小程序9月生命周期非兼容性改动

你弄一个仓库,把你的例子精简一下放上来啊

thisTom

comment created time in 4 months

push eventRubyLouvre/anu

司徒正美

commit sha 520d7c854cecf3ab0825a2642f5790dc73bcddb9

Update CHANGELOG.md

view details

RubyLouvre

commit sha b67f9954b757d3a243ec8e48085db2b843623daf

Merge branch 'branch3' of github.com:RubyLouvre/anu

view details

push time in 4 months

push eventRubyLouvre/anu

RubyLouvre

commit sha 9e16242b199a31ea4dfd533ef0d6d9f0edf7173f

1.6.1

view details

RubyLouvre

commit sha 7a46d0ecd44678d520dfc8047c3cdddc48ef2791

更新

view details

RubyLouvre

commit sha 04fae2ae9e6fec01b342510362ab670714c7bce6

Merge branch 'master' of github.com:RubyLouvre/anu

view details

push time in 4 months

created tagRubyLouvre/anu

tagv1.6.1

the React16-compat library with hooks https://rubylouvre.github.io/nanachi/

created time in 4 months

PR merged RubyLouvre/anu

fix: 修复在 Windows 下编译阻塞的问题
+2 -2

0 comment

1 changed file

GitaiQAQ

pr closed time in 4 months

push eventRubyLouvre/anu

Gitai

commit sha 8d3edac353275918b6cd7342552aadd806fb0f63

修复在 Windows 下编译阻塞的问题

view details

司徒正美

commit sha 7ec91b508af8b744e47d16f2e4a32a92e778e4c3

Merge pull request #1182 from GitaiQAQ/master fix: 修复在 Windows 下编译阻塞的问题

view details

push time in 4 months

push eventRubyLouvre/nanachi

RubyLouvre

commit sha 34c89a2d5f314b67b0c53972638db97f21a8451c

update

view details

push time in 4 months

startedmolefrog/wouter

started time in 4 months

push eventRubyLouvre/anu

司徒正美

commit sha d8e4f80adca318255172a0f9fd7603d80c2fbfc6

Update CHANGELOG.md update 1.3.4 log

view details

push time in 4 months

push eventRubyLouvre/anu

司徒正美

commit sha 520d7c854cecf3ab0825a2642f5790dc73bcddb9

Update CHANGELOG.md

view details

push time in 4 months

issue commentRubyLouvre/algorithmbook

求和问题

3sum smaller

function threeSumSmaller(nums, target){
    if(Object(nums).length < 3){
        return []
    }
    
    nums.sort((a, b)=> a-b);
    if(nums[0] >= target){
        return []
    }
    var sum = 0,condidtate = [],result = []
    function backtrack(start){
        if(condidtate.length == 3){
            if(sum < target){
                result.push(condidtate.concat())
            }
        }else{
            for(var i = start; i < nums.length; i++){
                sum += nums[i]
                condidtate.push(nums[i])
                backtrack(i+1)
                sum -= nums[i]
                condidtate.pop()
            }
        }
    }
    backtrack(0)
    console.log(result)
    return result;
}
threeSumSmaller([-2, 0, 1, 3], 2)
RubyLouvre

comment created time in 4 months

issue closedRubyLouvre/anu

React.lazy 加载的组件无法传递props

版本 anujs@1.6.0

React.lazy 加载的组件无法传递props

closed time in 5 months

menhal

issue commentRubyLouvre/anu

React.lazy 加载的组件无法传递props

已经修复

menhal

comment created time in 5 months

push eventRubyLouvre/anu

RubyLouvre

commit sha 27fd59e0dedffd2831a3870cd9c1be8dddd2b455

update

view details

push time in 5 months

push eventRubyLouvre/anu

RubyLouvre

commit sha 580536e930253b8f6b5b661cefa40315f339a1aa

合并分支3的feature,修复lazy不传递props的BUG

view details

push time in 5 months

push eventRubyLouvre/anu

blue.yang

commit sha 708a20d1fdc403f4efe5366467439c13b897f47e

Merge pull request #929 from taotao9125/branch3 fix path

view details

blue.yang

commit sha 3b505f3ddd118a937972c7e956de42953ae38316

Merge pull request #931 from RubyLouvre/webpackify Webpackify

view details

aweleey

commit sha 5566cdaec76987d6e03f4e8025fddc44d4ff0764

Merge remote-tracking branch 'upstream/branch3' into branch3

view details

aweleey

commit sha f4f2ccd5d2486356463f62bd09d3053a266b3579

Merge remote-tracking branch 'upstream/branch3' into branch3

view details

aweleey

commit sha 0024cf950f015695986db12dfece043593bdf76f

Merge remote-tracking branch 'upstream/branch3' into branch3

view details

shaoyudong

commit sha d096ba16b41c7529f4462cd81ea23decb6186621

chore: Version to 1.3.6-beta.1

view details

shaoyudong

commit sha bc468355ade6e1b4b316bc2b1a8cf3c48fb4dbe8

fix: h5 canIUse循环引用

view details

RubyLouvre

commit sha 5ac9f0118562ae55da73e33a34ebe19918b864c2

fix bug

view details

shaoyudong

commit sha 40efbed05b8ba3a39fb6c5606fcd69dbc4f04c47

fix: 支持typescript+mobx,解决ts装饰器转译与原先逻辑不一致问题

view details

shaoyudong

commit sha 3ac4fb48a1810204f97d74da35fec5e2b8552d9e

fix: conflict

view details

shaoyudong

commit sha 9aee7dfe0fa92e2df3309f5725d3254ff661ce24

chore: Version to 1.3.6-beta.2

view details

shaoyudong

commit sha a2e2d571bd3b482e57bbe459f2c34f3c085083f6

Merge pull request #1161 from shaoyudong/branch3 fix: 支持typescript+mobx,解决ts装饰器转译与原先逻辑不一致问题

view details

qitmac000964

commit sha b4f50c4d7537f6e984c060cc3162dc7d60c513e2

fix: 增加设置背景图片API

view details

qitmac000964

commit sha de1212669a467a4a6e2b507bdf0775d53ec668fe

fix: 增加设置背景图片API

view details

shaoyudong

commit sha e0dac99e1069c977886ccc2a9b9065970a0888f9

Merge pull request #1162 from gaoxiaomumu/branch3 Add setBackgroundColor&& setBackgroundTextStyle api

view details

RubyLouvre

commit sha 01587f8b5436688a5cfabb698b063fc5a990be29

onShow时也重新渲染页面

view details

RubyLouvre

commit sha dea3e3b35dc6fb2a2cc301cba580098217f98b0a

Merge branch 'branch3' of github.com:RubyLouvre/anu into branch3 # Conflicts: # dist/ReactAli.js # dist/ReactBu.js # dist/ReactH5.js # dist/ReactQuick.js # dist/ReactWX.js # packages/cli/lib/ReactAli.js # packages/cli/lib/ReactBu.js # packages/cli/lib/ReactH5.js # packages/cli/lib/ReactQuick.js # packages/cli/lib/ReactWX.js

view details

RubyLouvre

commit sha cf9dbaadc9bd1fd067c1e09332fc4f8f93b5147c

fix BUG

view details

shaoyudong

commit sha 7891ec9e480731d4bffa6472e2d37a1a57656382

fix: 删除mobx timer组件,写法错误

view details

shaoyudong

commit sha ca666951bdf5ebdef144ad1e4de807b26512cc00

Merge pull request #1163 from shaoyudong/branch3 fix: 删除mobx timer组件,写法错误

view details

push time in 5 months

PR merged RubyLouvre/anu

Branch3

添加改动

+6379 -6559

0 comment

115 changed files

RubyLouvre

pr closed time in 5 months

push eventRubyLouvre/anu

司徒正美

commit sha a56c0d09e5aee2fefd78a0ed515f38378c378262

Merge pull request #1160 from RubyLouvre/branch3 Branch3

view details

RubyLouvre

commit sha 86ea4da93615714dd07c5f2048c26a9f09baf21c

同步分支3的功能

view details

RubyLouvre

commit sha ed4cf8ed56e84b7bc46874488ef7c362c6d21f54

update

view details

RubyLouvre

commit sha 1dae00af223202746c7b3abfcc5786b583093970

1.6.0

view details

RubyLouvre

commit sha e2d8b78defb6d2c53a5fa7227a2638a74949a192

升级到1.6.0

view details

RubyLouvre

commit sha cfe07049901b8e3ad9d761abe9b5f962b80640dc

Merge branch 'master' of github.com:RubyLouvre/anu

view details

RubyLouvre

commit sha 9f4525127f6f9c3af67068f4b2d8dee4d6d59b33

update npmignore

view details

司徒正美

commit sha 4e3d91cf97968bee6af90d790a1e2272a7dbfcde

Update ReduxIE.js fix 小括号 BUG

view details

司徒正美

commit sha 4e2a32ca6f9630bd32b89a6addf39c73be5f49b9

Merge branch 'master' into branch3

view details

push time in 5 months

PR opened RubyLouvre/anu

Branch3

添加改动

+6397 -6775

0 comment

115 changed files

pr created time in 5 months

push eventRubyLouvre/anu

RubyLouvre

commit sha 68180b77519cf953a28c007a35a8247d950a89b4

修正lazy

view details

RubyLouvre

commit sha 75b50487629dfa22a8db1d3964b45e90aa91113b

Merge branch 'branch3' of github.com:RubyLouvre/anu into branch3

view details

push time in 5 months

issue commentRubyLouvre/anu

React.lazy 加载的组件无法传递props

明白了,它是这样传参的

var OtherComponent = lazy(() => {
    return new Promise(resolve =>
        setTimeout(
            () =>
                resolve({
                    default: function render(props) {
                        //export default
                        return <div>Hello,{props.name}</div>;
                    }
                }),
            3000
        )
    );
});

menhal

comment created time in 5 months

issue commentRubyLouvre/anu

React.lazy 加载的组件无法传递props

官方React也不能传props吧


var { lazy, Suspense } = React;
var OtherComponent = lazy((props) => {
    return new Promise(resolve =>
        setTimeout(
            () =>
                resolve({
                    default: function render() {
                        //export default
                        return <div>Hello,{props.name}</div>;
                    }
                }),
            3000
        )
    );
});
var valueRef = React.createRef()
class App extends React.Component {
    constructor(props){
        super(props)
        this.state = {
            name: "ruby"
        }
    }
    updateName(){
       var  name = valueRef.current.value;
       this.setState({name})
    }
    render() {
        return (
            <div>
                <p><input ref={valueRef} value={this.state.name} />{new Date-0}</p>
                <p><button onClick={this.updateName.bind(this)} type="button">提交</button></p>
                <Suspense fallback={<div>loading...</div>}>
                    <OtherComponent />
                </Suspense>
            </div>
        );
    }
}

ReactDOM.render(<App />, document.getElementById("root"));

这个也提示错误

menhal

comment created time in 5 months

issue commentRubyLouvre/algorithmbook

回溯问题

    function solveSudoku(board) {
            var result = []
            function backtrack(x, y) {
                if (x == 9) {
                    board.forEach(function (row) {
                        result.push(row.concat())
                    })
                    return true
                } else {


                    if (board[x][y] == '.') {
                        for (var i = 1; i <= 9; i++) {
                            if (check(board, x, y, i + '')) {
                                board[x][y] = i + ""
                                if (backtrack((y == 8 ? x + 1 : x), (y == 8 ? 0 : y + 1))) {
                                    return true
                                }
                            }
                        }
                        board[x][y] = '.';
                    } else {
                        if (backtrack((y == 8 ? x + 1 : x), (y == 8 ? 0 : y + 1))) {
                            return true
                        }
                    }
                }

            }
            function check(board, x, y, k) {
                for (var i = 0; i < 9; i++) {
                    //我们想在board[x][y] 中填入k, 结果在board[x][i] 或 board[i][y] 出现相同的k
                    if (board[x][i] == k || board[i][y] == k) {
                        return false;
                    }
                }
                //检查九宫格
                var xx = Math.floor(x / 3)
                var yy = Math.floor(y / 3)
                for (var i = xx * 3; i < (xx + 1) * 3; i++) {
                    for (var j = yy * 3; j < (yy + 1) * 3; j++) {
                        if (board[i][j] == k) {
                            return false;
                        }
                    }
                }
                return true;
            }
            backtrack(0, 0)
            console.log(JSON.stringify(result))
            return result;
        }
RubyLouvre

comment created time in 5 months

issue commentRubyLouvre/algorithmbook

回溯问题

数独问题

你一定听说过“数独”游戏。 如下图所示,玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个同色九宫内的数字均含1-9,不重复。 数独的答案都是唯一的,所以,多个解也称为无解。 本图的数字据说是芬兰数学家花了3个月的时间设计出来的较难的题目。但对会使用计算机编程的你来说,恐怕易如反掌了。 本题的要求就是输入数独题目,程序输出数独的唯一解。我们保证所有已知数据的格式都是合法的,并且题目有唯一的解。 格式要求,输入9行,每行9个数字,0代表未知,其它数字为已知。 输出9行,每行9个数字表示数独的解。 输入:

005300000 800000020 070010500 400005300 010070006 003200080 060500009 004000030 000009700

程序应该输出: 145327698 839654127 672918543 496185372 218473956 753296481 367542819 984761235 521839764

再例如,输入: 800000000 003600000 070090200 050007000 000045700 000100030 001000068 008500010 090000400

程序应该输出:  812753649 943682175 675491283 154237896 369845721 287169534 521974368 438526917 796318452

数独游戏使用深度优先搜索的方法是比较方便的,可以搜出数独的所有合法的解(使用其他的方法来解决是非常困难的或者是不可能的) image

function solveSudoku(board) {
    var result = []
    function backtrack(x, y) {
        if (x == 9) {
            board.forEach(function (row) {
                result.push(row.concat())
            })
            return true
        } else {
            if (board[x][y] == '.') {
                for (var i = 1; i <= 9; i++) {
                    if (check(board, x, y, i)) {
                        board[x][y] = i + ""
                        if (backtrack(x + Math.floor((y + 1) / 9), (y + 1) % 9)) {
                            return true
                        }
                    }
                }
                board[x][y] = '.';
            } else {
                if (backtrack(x + Math.floor((y + 1) / 9), (y + 1) % 9)) {
                    return true
                }
            }
        }

    }
    function check(board, x, y, k) {
        for (var i = 0; i < 9; i++) {
            //我们想在board[x][y] 中填入k, 结果在board[x][i] 或 board[i][y] 出现相同的k
            if (board[x][i] == k + '' || board[i][y] == '' + k) {
                return false;
            }
        }
        //检查九宫格
        var xx = Math.floor(x / 3)
        var yy = Math.floor(y / 3)
        for (var i = xx * 3; i < (xx + 1) * 3; i++) {
            for (var j = yy * 3; j < (yy + 1) * 3; j++) {
                if (board[i][j] == '' + k) {
                    return false;
                }
            }
        }
        return true;
    }
    backtrack(0, 0)
    console.log(JSON.stringify(result))
    return result;
}
solveSudoku(
    [["5", "3", ".", ".", "7", ".", ".", ".", "."],
    ["6", ".", ".", "1", "9", "5", ".", ".", "."],
    [".", "9", "8", ".", ".", ".", ".", "6", "."],
    ["8", ".", ".", ".", "6", ".", ".", ".", "3"],
    ["4", ".", ".", "8", ".", "3", ".", ".", "1"],
    ["7", ".", ".", ".", "2", ".", ".", ".", "6"],
    [".", "6", ".", ".", ".", ".", "2", "8", "."],
    [".", ".", ".", "4", "1", "9", ".", ".", "5"],
    [".", ".", ".", ".", "8", ".", ".", "7", "9"]]
)
RubyLouvre

comment created time in 5 months

issue commentRubyLouvre/algorithmbook

求和问题

https://blog.csdn.net/haolexiao/article/details/70768526

RubyLouvre

comment created time in 5 months

issue commentRubyLouvre/algorithmbook

求和问题

3sum

function twoSum(nums, target, start, result) {
    var i = start;
    var j = nums.length - 1;
    var k = start - 1;
    while (i < j) {
        var sum = nums[i] + nums[j];
        if (sum == target) {
            result.push([nums[k], nums[i], nums[j]]);
            //处理重复的情况
            i++;
            j--;
            while (i < j && nums[i] == nums[i - 1]) i++;
            while (i < j && nums[j + 1] == nums[j]) j--;
        } else if (sum < target) {
            i++;
        } else {
            j--;
        }
    }
}
function threeSum(nums) {
    var n = nums.length;
    var result = [];
    nums.sort((a, b) => a - b);
    for (var i = 0; i < n; i++) {
        if (i > 0 && nums[i] == nums[i - 1]) {
            continue;
        }
        twoSum(nums, -nums[i], i + 1, result);
    }
    console.log(result);
    return result;
}

threeSum([-1, 0, 1, 2, -1, -4]);
RubyLouvre

comment created time in 5 months

issue commentRubyLouvre/algorithmbook

求和问题

2sum 如果只考虑元素, 那么我们可以排序

function twoSum(nums, target) {
    var result = [];
    nums.sort((a, b) => a - b);
    var i =0, j = nums.length - 1;
    while (i < j) {
        var sum = nums[i] + nums[j];
        if (sum == target) {
            result.push([nums[i], nums[j]]);
            //处理重复的情况
            i++;
            j--;
            while (i < j && nums[i] == nums[i - 1]) i++;
            while (i < j && nums[j + 1] == nums[j]) j--;
        } else if (sum < target) {
            i++;
        } else {
            j--;
        }
    }
    // console.log(result)
    return result;
}

twoSum( [2, 7, 11, 15], 9)
RubyLouvre

comment created time in 5 months

issue commentRubyLouvre/algorithmbook

求和问题

LeetCode 16 3Sum Closest

Given an array nums of n integers and an integer target, find three integers in nums such that the sum is closest to target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

Example:

Given array nums = [-1, 2, 1, -4], and target = 1.

The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

function threeSumClosest(nums, target) {
    nums.sort((a, b) => a - b);
    var end = nums.length;
    var val = 0, sum = Infinity
    function backtrack(start, n) {
        if (n == 3) {
            if(Math.abs(val - target) < Math.abs(sum - target)){
                sum =  val
            }
        } else {
            for (var i = start; i < nums.length; i++) {
                val += nums[i];
                backtrack(i + 1, n+1)
                val -= nums[i];
            }
        }
    }
    backtrack(0, 0);
    console.log(sum);
    return sum;
}

threeSumClosest([-1, 2, 1 ,-4], 1);
RubyLouvre

comment created time in 5 months

issue openedRubyLouvre/algorithmbook

求和问题

3sum

使用回溯法

function threeSum(nums) {
    var result = [],
        condidate = [],
        target = 0;
        nums.sort((a,b)=>a-b)
    function backtrack(start) {
        if (condidate.length === 3 && target == 0) {
            result.push(condidate.concat());
        } else {
            for (var i = start; i < nums.length; i++) {
                if(i != start && nums[i] == nums[i-1]){
                    continue
                }
                var el = nums[i]
                condidate.push(el);
                target += el
                backtrack(i + 1);
                target -= el
                condidate.pop();
            }
        }
    }
    backtrack(0); 
    return result;
}
threeSum( [-1, 0, 1, 2, -1, -4]);

超时

created time in 5 months

push eventRubyLouvre/nanachi

RubyLouvre

commit sha e20d34c4c6eab312b578e73772da252110e3592a

xxxx

view details

push time in 5 months

push eventRubyLouvre/anu

aweleey

commit sha 64a472078c1865ed3d682f712dd3e8072388cb95

opti: add React.api.createInnerAudioContext()

view details

aweleey

commit sha 4302cbd22cea63089a18002ba3dfc27d28db8d4e

opti: remove console

view details

司徒正美

commit sha 0ee42f6763526fa88b1cd657051110c57b721942

Merge pull request #1179 from aweleey/branch3 React.api.createInnerAudioContext()

view details

push time in 5 months

PR merged RubyLouvre/anu

React.api.createInnerAudioContext()

添加 React.api.createInnerAudioContext() 方法,使用方法同步微信小程序

  • 因为 iOS Safari 的限制,volume 设置不生效(Android和PC目前正常)
  • h5 audio 的原生 api 没有 stop 方法和事件,可以使用 pause() 加上 seek(0) 代替(即: 暂停 加上 跳转到开头)
+499 -0

0 comment

4 changed files

aweleey

pr closed time in 5 months

issue commentRubyLouvre/anu

React.lazy 加载的组件无法传递props

有例子吗,我看你是怎么传props ?

menhal

comment created time in 5 months

push eventRubyLouvre/nanachi

RubyLouvre

commit sha 78db34846e4fafb29a0981ebd94d60ef130fd666

update

view details

push time in 5 months

push eventRubyLouvre/anu

RubyLouvre

commit sha 9c726e8c19b273f778f602153e12c3a1315f1fa6

更新版本

view details

push time in 5 months

push eventRubyLouvre/anu

RubyLouvre

commit sha bb418747becc4639f97f931591d0516e64fdb0e2

修得百度小程序 使用mobx-react时真机预览时组件名被压缩掉的

view details

push time in 5 months

push eventRubyLouvre/anu

RubyLouvre

commit sha ed8a06452a8d1e2d9bfd2b082337ee0a767e5d11

修正百度使用mobx时真机预览时被压缩的问题

view details

RubyLouvre

commit sha 3c23aec592e503617898f74aba94c9bd67a49e57

Merge branch 'branch3' of github.com:RubyLouvre/anu into branch3

view details

push time in 5 months

more