JunQu / ARTS

ARTS Practice
Apache License 2.0
1 stars 0 forks source link

第一周的ARTS #2

Open JunQu opened 3 years ago

JunQu commented 3 years ago

Algorithm

万事从头开始,从 leetcode 第一题 Two Sum 开始。

这个问题相信不必多说,毕竟第一题,我说一下可能需要注意的点

暴力法

直接遍历所有可能性,然后找到相符合的目标(target),那么代码就是:

const twoSum = (nums, target) => {
  for (let i = 0; i < nums.length; i++) {
    for (let j = i + 1; j < nums.length; j++) {
      if (nums[i] + nums[j] === target) {
        return [i, j];
      }
    }
  }
}

暴力法其实并不是一开始想到办法,因为时间复杂度是 O(n*n) 这个在很多时候是不能接受的。 当然在这道题其实是可以接受的,因为题目条件范围是 2 <= nums.length <= 10**3,即使是最大的情况下 10**6 相对来说也不是特别大,果然我的提交验证了我的想法。

Screen Shot 2021-04-24 at 11 40 18 PM

双指针

学习数据结构的时候,老师曾提醒过,当遇到 O(n * n) 的情况,很多时候都是可以优化成 O(n*logn),这是一个相对可以接受的复杂度。也是我一开始的想法,拿到这个就想到有没有可能一遍过。如果是 O(n*logn) 那么首先考虑的就是排序,因为排序一般期望的复杂度就是O(n*logn),既然排序了,那么数字是从小到大的,而且确定了目标值(target),从两端或者从中间的方法,双指针的想法也就自然而然的想到了。 于是双指针的解法如下:

const twoSum = (nums, target) => {
    const copyNums = nums.slice(0);
    const sortedNums = nums.sort((a,b)=>a-b);
    let leftPoint = 0;
    let rightPoint = sortedNums.length - 1;
    while (leftPoint < rightPoint) {
      const sum = sortedNums[leftPoint] + sortedNums[rightPoint];
      if (sum > target) {
        rightPoint--;
      } else if (sum < target) {
        leftPoint++;
      } else {
        break;
      }
    }
    if(leftPoint===rightPoint) {
      return undefined;  // not find
    }
    const leftValue = copyNums.indexOf(sortedNums[leftPoint]);
    const rightValue = copyNums.lastIndexOf(sortedNums[rightPoint]);
    return [leftValue, rightValue];
};

这一次时间上就超过了 80.29% 相对暴力法的 6.45% 进步了不少。

一次遍历

如果说 n 个元素,一般认为最好期望是 o(n)。在 O(1) 这样的复杂度通常是非常消耗空间的情况,而 O(logn)往往是特殊的数学技巧或者方法,我目前能做的就是尽量是在O(n)的复杂度。那么这个有没有可能 O(n),还是有的。通过空间换取时间,我们回想目标(target),假如我们确定了一个值,是不是也同时确定了另一个值,于是我们可以通过记住所有的值来判断有没有另一个我们要找的值。所以可以通过构造一个哈希字典记住之前的值和索引,记住值是为了方便判断是否存在,记住索引是为了返回。得到这个思路,我们可以一次遍历就能得出结果。

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

因为哈希字典的存取视为 O(1),这一次整体的复杂度就是 O(n),终于到达了想要的最佳期望。不过在上面的提交后时间并不快,甚至比双指针慢,可能是leetcode的原因。而且看了最佳答案发现还有个点可以优化,map.has 换成 map.get想想也是会快一点,不过我不准备换了,因为这样更容易看懂一些。

BTW

可能是 js 的强大 v8 或者 leetcode 的关系,可能你会发现 for 循环有时候甚至不如 forEach map 这些快,只能佩服v8的优化,但是我应该不会选择这些,尽量少用 js 特性而去纯粹的刷题, 尽量去用最原始的方式就是我的一个方式,即大概我不会使用一行代码去解决了。每个人追求目标或许相同,但是每个人经过的路途可以不同。

JunQu commented 3 years ago

Review

原文链接:core-web-vitals Web Vitals 适用于所有网页的性能检测,而 Core Web Vitals 是属于Web Vitals的一部分。Core Web Vitals 应该是由网站的所有者自己测量,并且可以通过所有(相关的)Google工具呈现。每个Core Web Vital代表着用户体验的不同方面,可以现场测试,反映了用户真实体验的重要结果。 Core Web Vitals 的指标会随着时间的增长而不断变化,当前2020年的指标关注用户体验的三个方面:页面加载,页面交互性,视觉稳定性。包含接下来的指标(及其阈值)。 最大内容绘制时间(LCP):(这项指标)衡量页面加载的性能。为了给用户一个更好的体验,LCP应该在页面首次开始加载后的2.5秒内开始。 第一次输入延迟时间(FID):(这项指标)衡量页面可交互性。为了给用户一个更好的体验,页面的FID应当不超过100毫秒。 累计页面布局的变化(CLS):(这项指标)衡量页面视觉稳定性。为了给用户一个更好的体验,页面应当保持CLS的值不超过0.1。

为什么翻译这个? 因为最近 Web Vitals 包已经发布正式版 1.1.1了,而且被 create-react-app 内置,我很看好他以用户体验衡量页面性能的方式。

单词 非常多不认识的,也不好翻译的词,导致翻译的让人看不懂。 measured 慎重的,经过仔细思考的。 surfaced 表层,表面,外层。 distinct 明显的,显著的,确实的 critical 批判的,关键的,重大的,挑剔的,严厉的 outcome结果,后果,效果 interactive交互,互动

JunQu commented 3 years ago

Tip

|| vs ?? in JavaScript

在js中: ||: 逻辑运算符,如果左边的值为 Falsy 则返回右边的值。 ??:空值合并运算符,左边为null或者undefined 则返回右边的值。

看描述就会有很多的区别,其实他们是相关的,从范围来看 ?? 属于 ||

const a = undefined || 'a';
const b = null || 'b';
const c = undefined ?? 'c';
const d = null ?? 'd';
console.log(a,b,c,d); // a b c d

而因为推出了可选操作符?. 导致了一些联动例如 a?.b?.c ?? d 这个如果 a b c 无论哪一个是undefined 或者 null 都会返回 d,这样保证了安全的访问和默认值。所以现在很多之前写默认值的通过||也可以转为更好的??。 但是如果你有更多的选择,比如我希望金额为0时,显示为 0.00,可以写成 product?.price || '0.00'.

这两个操作符有部分重叠,我们可以挑选更好的方式完成我们的目标,不只纯粹的只用某一个。

JunQu commented 3 years ago

Share

思维分享

投资和治癌的相似之处:想要不被癌症杀死,最有效的办法,是降低自己生癌的概率。简而言之就是不吸烟,不喝酒,不熬夜,坚持锻炼,饮食健康,劳逸结合。这些方法没啥秘密可言,你也不需要花钱去买,但是它们听起来很无聊,而且要长期坚持。然而大家最感兴趣的,却是那些能够治愈癌症的特效药。最好是几个月就能把癌细胞杀死,让病人起死回生。问题在于,全世界最聪明的科学家们研究了几十年,还是没有找到这样的特效药。 投资也是类似。多元分散,控制成本,长期坚持,搞懂了这几个原则并且耐心坚持的话,你的投资回报不会太差,而且不太可能爆仓而蒙受重大损失。但是很多人觉得这样的方法太无聊,太没有挑战性,致富太慢。他们宁愿铤而走险,追求能够让他们一夜致富的特效投资方法,却没有意识到自己只是在捞水中月而已。 — 伍治坚的知乎想法

这是影响我四月判断的想法,周围朋友同学都买基金、股票,甚至炒币,而我一直未曾尝试去投资理财,当然主要原因是没钱,现在我也记下了,好好的健身、睡觉,慢慢的积累起来。

技术分享:

商业项目如何选择框架: https://mp.weixin.qq.com/s/Enrfxoi4xbftoKCEiFi01Q 前端的内存优化:https://mp.weixin.qq.com/s/_wbP0B3EiTjME9Sg3BXqqA 张鑫旭的js视频解码: https://www.zhangxinxu.com/wordpress/2021/04/js-video-decode-jsmpeg-broadway/ 如何使用 React devtool 检测你react网页的性能:https://blog.asayer.io/the-definitive-guide-to-profiling-react-applications

JunQu commented 3 years ago

靡不有初 鲜克有终

间歇性踌躇满志,持续性混吃等死,多次学习都被我放弃,希望能坚持至少一年。

第一篇完成的比较随意,不知如何去做,可能已经在悠闲的环境太久,我需要改进一些问题。

Lijie0981 commented 3 years ago

简单看了下web vitals 的源码,感觉后面可以讲解下。Performance Api 以及为啥包体积这么小(~1K)。 Tips 不错,之前也看过 ??的文章,不过没有用过,一般都用 ||。 记得之前有篇文章里面说,不太建议写短路语句。具体原因是因为短路意义会和判断语句造成混淆。

Share 内容也很不错,不过认同和做到是两回事。做到太难了,人很懒,天生会想要去做一些一本万利的事情。客服自己人性的弱点,才能不成为普通人。我们的坚持也是。 算法的内容我现在还没太能投入思考,会有主观的恐惧。还是要练习,并面对。

JunQu commented 3 years ago

@Lijie0981

web vitals 体积确实很小,因为它检测的值也不是很多,可能大多是一些调用了浏览器API来实现所以体积小,我目前也有使用。关于源码部分确实可以看看,毕竟已经正式版本了,这个倒是也是给了我一个思路,我想以后试试它的源码当作 ts 的练手。

关于可选链操作符?.其实可以试试,因为它解决的是一些语法上某些优雅的问题, 如果不同可选链接

if (bigObject && 
    bigObject.prop1 != null && 
    bigObject.prop1.prop2 != null) {
  let result = bigObject.prop1.prop2.value;
}

对比用了可选链操作符:

 let result = bigObject?.prop1?.prop2?.value

显然可以看出冗余程度和对视觉友好度。而且它就像 async/await 一样,抄的隔壁 c# 的,js 抄的语法大多是不错的。不过如果配合三目运算确实会让人有点疑惑,类似下面的代码:

const result = !foo?.bar ? other?.value : theOther?.value ?? 'default';

几乎没人一眼就能看懂这些,就像函数式编程一样的令人费解的解读一行代码,但是这是人为的与三目运算混搭,人为的混淆可能只为某些炫技,如果写成 if/else 照样挺不错的,我们也可以把它加上一些括号进行区分。而且大多时候我认为这个语法糖挺甜的,不然很多深层次属性的访问判断写起来让人很不爽。最后语法糖几乎是进步的,是时代各类语言互相“借鉴”的优秀结果。而js自身的 private 属性就挺让人难受和本身也有点奇怪,明明好的不抄,非要自己弄个独特的 private 。

算法我也不会,对算法我就那三板斧,全用在 towSum 上了,不过必须得练起了。不过我感觉你们算法应该是信手拈来呀,大厂面试先上算法开胃,算法有想法可以交流起来。

Lijie0981 commented 3 years ago

是的,一般情况下,代码的可读性排第一位。

JunQu commented 3 years ago

所以这个就用来访问属性就好,别与不好读懂的三目运算混搭,混搭了也要加括号区分

tinaxu-come-on commented 3 years ago

算法那些对于前端来说还是用的比较少,可能也是没有比较复杂的场景,数据处理都在后端了,如果放在前端对于性能还是有些影响。

|| vs ?? 这种我还是比较倾向写|| ,??我估计自己写出来,等后面看代码还得研究到底是什么意思 ,下次遇到可用的场景可以试试。

关于性能方面,没有过多的去研究,我们现在的项目都没有要求,我觉得代码写的健壮,易扩展就已经很不错了。

关于生活,多运动,身体健康比什么都强。