2020-05-24学习随笔

序言

学习随笔是本人对自己一天的自学回顾,由于本人是非科班出身,不懂很多cs的专业术语,所以难免会有些错误,望各位批评指正,本人定当悉心接受并立即改正。希望自己能够慢慢坚持下去,坚持转行的道路,坚持每天学习的输出。

刷题篇

LeetCode

1.题目

给定两个(单向)链表,判定它们是否相交并返回交点。

2.大致思路

两人在长度不同的赛道跑步(匀速且两人速度相同),当跑完自己的赛道时,再从另一人赛道起点继续跑,如果两人能够相遇,则相遇点就是赛道的交点。

双指针分别指向两个链表,即p指向链表A,q指向链表B。同时开始遍历链表,p到表尾时,next指向链表B,q到表尾时,next指向A。直到p=q。

这里我产生了一个误区,第一次写出这个代码的时候我以为如果两链表没有交点的话,会无限循环,但我错了,具体看代码。

3.代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    struct ListNode *p=headA,*q=headB;
    while(p!=q){      //这里,我本以为无交点会无限循环,但不会的。
                     //因为,两个指针走的距离是相同的。
                    //若没有交点,也就是说两指针会同时到达表尾,即为NULL,p=q跳出循环。
        if(p) p=p->next;
        else p=headB;
        if(q) q=q->next;
        else q=headA;
    }
    return p;
}

4.其他解法

1.暴力解法

一个一个比较结点是否相同,若有相同的结点,即返回此结点,否则返回NULL

2.通过长度求解

若两链表长度不同,两链表有交点且在交点前的部分链表长度不同,即从起点到交点,两指针走的距离不同,只要让两指针离交点距离相同即可。即让离交点远的指针先走一段距离,这段距离即为两链表长度之差。

这里说明一下:从交点开始往后,两链表的结点都是相同的,所以长度不同是由于交点前长度不同引起的。

数据结构

1.顺序表的查找

直接上代码(来自于《大话数据结构》,有几个问题)

int Sequential_Search(int *a,int n,int key){
    //在长度为n的数组a中,查找key,找到返回其位置,否则返回0
    int i;
    for(i=1;i<=n;i++){
        /*
            这里可以看到,i是从1开始,也就是说,是从a[1]到a[n]查找
            为什么呢,那第一个a[0]不就漏了,还有,数组长度不是只有n吗,不会越界吗?
            在我看来,这里的a相当于一个线性表,线性表长度在任何时候都是小于数组的,所以不会越界
            从a[1]开始找,若key在a[0],找不到即返回0,相当于找到了,会不会引起歧义?
        */    
        if(a[i]==key)
        return i;
    }
    return 0;
}

由于每次都要判断i是否小于等于n,即判断是否越界,比较麻烦,故加入哨兵。

改进代码如下(加哨兵

int Sequential_Search(int *a,int n,int key){
    int i;
    a[0]=key;
    i=n;
    while(a[i]!=key){
        i--;
    }
    return i;
}

2.有序表的查找

1.二分(折半)查找

关键代码   mid = (low+high)/2

思考:为什么判断条件是low<=high而不是low!=high呢???

2.插值查找

关键代码   mid=low + ((key-a[low])/(a[high]-a[low]))*(high-low)

3.斐波那契查找(这个需要多思考一下)

关键在于确定数组长度n位于斐波那契数列数列的位置k

int Fibonacci_Search(int *a,int n,int key){
    int low,high,mid,i,k;
    low=1;
    high=n;
    k=0;
    while(n>F[k]-1) {k++;}   //这里F即为斐波那契数列
    for(i=n;i<F[k-1]-1;i++) {a[i]=a[n];}   //这里还要补全数值,防止越界
    while(low<=high){
         mid=low+F[k-1]-1;
        if(key<a[mid]){
            high=mid-1;
            k=k-1;
        }
        else if(key>a[mid]){
            low=mid+1;
            k=k-2;
        }
        else{
            if(mid<n) return mid;
            else return n;
        }
    }
    return 0;
}

3.线性索引

1.稠密索引:有多少数据就要多少索引项,空间代价大

2.分块索引:

三个关键要素:最大关键码,块长,块首元素指针

两个性质:块内元素无序,块与块之间有序

查找方式:先查块(有序,则可用二分或插值查找),再查找块中元素(无序,顺序查找)

最大关键码的用处:

比如有分别以27,57,96为最大关键码的三个块,我要找77可能在哪个块,即57<77<96,所以在第三个块中找。

3.倒排索引(没有过多了解)

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容