ARTS #002

ARTS #002

Posted by Dan on August 7, 2018

ARTS是由左耳朵耗子--陈皓发起的一个活动: 每周至少做一个leetcode的算法题、阅读并点评至少一篇英文技术文章、学习至少一个技术技巧、分享一篇有观点和思考的文章。(也就是Algorithm、Review、Tip、Share简称ARTS),至少坚持一年。

ARTS 002

这是第二篇,写的比较水,希望以后越来越好。

Algorihm 算法题

leetcode 算法第242题 Valid Anagram(验证是否是异位词)

Given two strings s and t , write a function to determine if t is an anagram of s.
Example 1:
Input: s = "anagram", t = "nagaram"
Output: true
Example 2:
Input: s = "rat", t = "car"
Output: false
Note:
You may assume the string contains only lowercase alphabets.

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的一个字母异位词。
示例 1:
输入: s = "anagram", t = "nagaram"
输出: true
示例 2:
输入: s = "rat", t = "car"
输出: false
说明:
你可以假设字符串只包含小写字母。

刚开始的想法是先排序,后比较,就是先对两个字符串进行排序,然后再比较是否相等,这种验证方式是最低效的,排序的时候可以用到冒泡排序、选择排序、插入排序等,虽然这三种排序算法的复杂度都是O(n2),但是测试发现在数据量很多的情况下,插入排序要比另外两种快很多,根本不在一个数量级,用插入排序实现如下:

char* insertionSort(char* str) {
    for (int j = 1; j < strlen(str); j++) {
        char *insertionChar = str + j;
        char iChar = *insertionChar;
        char * compareChar = insertionChar;
        
        for (int i = j-1; i >=0; i--) {
            if (iChar < *(str + i)) {
                compareChar = str + i;
                *(compareChar +1) = *compareChar;
            }
            else{
                break;
            }
        }
        *compareChar = iChar;
    }
    return str;
}

bool isAnagram(char* s, char* t) {
    if (strlen(s) != strlen(t)){
        return false;
    }
    char *s1 = insertionSort(s);
    char *s2 = insertionSort(t);
    
    if (strcmp(s1,s2)) {
        return false;
    }
    else{
        return true;
    }
}

但是在leetcode根本通不过,leetcode上的测试数据的字符串的长度有100Kb大小,我本地测了一下用插入排序用了近20秒,但是如果用冒泡和选择排序,反正我是跑了一个多小时没跑完。

这个方法不行就换一种思路了,可以通过统计字符串包含的字符类型和个数是否相等,比如s字符串包含字母a10个,字母b5个,字母k8个,如果t字符串也是这样,那么s就是t的异位词。实现如下

bool isAnagram(char* s, char* t) {
    if (strlen(s) != strlen(t)){
        return false;
    }

    int af[26]= {0};
    while (*s) {
        af[*s++ - 'a']+=1;
    }
    while (*t) {
        af[*t++  - 'a']-=1;
    }
    
    for (int i = 0; i<26; i++) {
        if (af[i] != 0) {
            return false;
        }
    }
    return true;
}

这里实现的时候,只用了一个数组,而不是用两个数组分别统计字符在两个字符串中出现的个数,这么做可以避免由于某个字符出现的次数过多,出现越界的情况。

Review

下面这篇文章来自:https://littlebitesofcocoa.com/251-face-aware-image-views-with-aspectfillfaceaware; 讲的是使用aspectfillfaceaware,来实现给imageView设置图片的时候,如果图片中包含人脸,可以自动让人脸居中显示。

Face Aware Image Views with AspectFillFaceAware (用AspectFillFaceAware让imageView识别人脸)

When using UIImageViews, sometimes the built-in content modes can cramp our style.

使用UIImageViews时,有时内置的内容模式会破坏我们的风格,不能满足我们的需求。

Many times, we’re displaying photos of people. In these cases, it’d be great if the image view could somehow be told to intelligently crop the photo around the person’s face.

很多时候,我们展示的是人物的照片。 在这些情况下,如果图像视图可以以某种方式智能地在人的脸部周围裁剪照片,那就太棒了。

Today we’ll check out a library from Beau Nouvelle called AspectFillFaceAware. It’s super simple, let’s take a look.

今天我们将看看Beau Nouvelle的一个名为AspectFillFaceAware的类库。 它非常简单,让我们来看看。

AspectFillFaceAware is essentially just an extension on UIImageView. It provides two ways to configure an image view to be “face aware”.

AspectFillFaceAware本质上只是UIImageView的扩展。 它提供了两种将图像视图配置为“面部识别”的方法。

The first is in Interface Builder, we can enable the feature by flipping on the feature in the Inspector. (Not seeing the option? Run your project once, then it should appear).

第一种方法是在Interface Builder中,我们可以通过翻阅Inspector中的功能来启用该功能。 (没有看到选项?运行您的项目一次,然后它应该出现)。

Here’s the how it looks:

We can also enable the functionality in code by setting the image view’s image using this new function:

我们还可以通过代码的方式使用此新功能:

imageView.set(image: avatar, focusOnFaces: true) We can even throw a quick corner radius on the image view’s layer to try out the “face aware” functionality on a circular view. (i.e. user avatars):

我们甚至可以在图像视图的图层上抛出一个快速角半径,以在圆形视图上尝试“面部识别”功能。 (即用户头像):

let radius = imageView.bounds.size.width / 2.0 imageView.layer.cornerRadius = radius

Under the hood, the library is using a low accuracy CIDetector with a type of CIDetectorTypeFace to handle the actual face detection. Want to dive deeper here? We covered CIDetectors way back in Bite #87.

在引擎盖下,库正在使用具有CIDetectorTypeFace类型的低精度CIDetector来处理实际的面部检测。 想深入研究吗? 我们在Bite #87.中介绍了CIDetectors的方法

Tip

介绍一下使用Proxifiershadowsocks实现二级代理上网的方法。 有的公司上网需要通过代理,这时我们就无法使用shadowsocks进行代理上网了,比如我目前所在的公司就是通过代理上网的,要想访问外网就必须代理到公司的服务器才能上网,这样的话直接使用shadowsocks就不行了。 如果想办法让shadowsocks也走代理是不是就行了呢。于是就找到了Proxifier这个软件。 Proxifier,该工具的作用就是接管运行中的所有应用发出的所有请求,然后就可以控制某个应用程序是否走代理了,这样就可以让不支持代理的应用也可以走代理了。 本来ss客户端(shadowsocks)是直接访问ss代理服务器的,通过Proxifier可以控制让ss客户端先走公司代理,然后再走ss代理服务器,大致流程如下

  • 设置过程如下: 打开Proxifier,选择Proxies选项卡设置公司的HTTP代理以及本地Socks5代理:

127.0.0.1的端口可以打开 ShadowSocks的高级配置查看 启动ShadowSocks客户端,就会发现Proxifier自动捕获到了名为ss-local的应用,就是由ShadowSocks开启的SS客户端,将其的代理规则设置为之前创建好的公司代理: 然后让Localhost和Default走ss-local(图中的最后两项)。

可以看到前面3个配置的是Direct,有的网站或应用不需要走代理的可以这么设置。 如果发现启用Proxifier后有的应用出现问题,很可能是代理导致的,比如,启动Proxifier后,我用Xcode运行C程序的时候发现一直卡着,后来发现xcode运行C程序的时候,会自动启动一个debugserver的本地服务,由于我设置的默认走代理,所以这个服务就不能正常通信了,把debugserver改为Direct可以正常运行了。 可以看到Proxifier可以直接指定某个应用名是否走代理,也可以指定某个IP是否走代理,使用起来确实很方便。

参考文章: http://www.devtalking.com/articles/shadowsocks-guide/ http://blackwolfsec.cc/2016/09/19/Proxifier_Shadowshocks/ https://github.com/cyfdecyf/cow/blob/master/doc/sample-config/rc https://www.latoooo.com/xia_zhe_teng/179.htm http://haoweiguang.me/2017/05/08/Mac%E4%B8%8Bshadowsocks%E5%85%A8%E8%87%AA%E5%8A%A8%E5%9C%B0%E4%BB%A3%E7%90%86%E7%BF%BB%E5%A2%99/ https://blog.e9china.net/tufan/macshanganzhuangcowproxyfanqiangjiaocheng.html

Share

最近换了一个公司,一个加班比较严重的公司,刚来的时候一直想走,后来想想还是算了,一个公司能做这么大(听说研发有近2万人)肯定有值得学习的地方,所以决定静下心来学习一下,对于加班,加班的时候可以学习,提高自己的能力,之所以来这个公司,还不是因为自己的技术水平还不够好,所以要尽快提高自己,不知道在哪看到一句话要么忍,要么滚,能力强的话肯定滚到更好的公司了,既然滚不了,就要静下心来好好提高自己,不要发牢骚有情绪。

实际上很多事就是这样的,当你的能力配不上你的野心的时候,你要做的是提高你的能力,而不是抱怨环境。