妥妥的去面试之数据结构与算法(二)

笔者由于在找工作,所以近期最主要的任务就是准备面试,不打无准备之仗。只有你准备充分了,那么你想要的机会才有机会入你怀中。

笔者会将准备面试的学习过程记录下来,方便自己复盘的同时也希望能给一道找工作的小伙伴们一些帮助。笔者准备的内容大纲如下

Android面试大纲.png

妥妥的去面试之数据结构与算法(一)

下面是本篇博客的正菜部分:

倒数第K个节点

在一个单链表中找到倒数第k个节点

很容易想到先遍历一次链表节点个数n,第二次遍历只需要找第n-k+1个节点。

当你说出这个想法的时候,面试官肯定会提示你他期待的答案是只允许遍历一次链表

关键点:是否可以想到使用两个指针,移动过程中两个所在位置始终相差k-1的距离。当前一个指针移到尾部时,后一个指针正好指向倒数第k个结点。

    public ListNode findKthTail(ListNode pHead, int k){
        if(pHead == null || k<=0) return null;
        ListNode pAHead = pHead;      
        ListNode pBehind = null;
        
        //使前面的指针快与后面的节点k-1个节点位
        for(int i=0;i<k-1;i++){
            if(pAHead.next != null){  //容易忽视隐藏的边界条件,有可能k的值大于节点数
                pAHead = pAHead.next;
            }else{
                return null;
            }   
        }
        //让两个指针始终保持k-1个节点位,等前面的节点到尾节点时,后一个节点到达倒数第k个节点
        pBehind = pHead;
        while(pAHead.next != null){
            pAHead = pAHead.next;
            pBehind = pBehind.next;
        }
        return pBehind;
    }

引申:如果让一次遍历找链表的中间结点可以使用类似的方法。只需要在指针移动时,前一个指针一次移动两个节点,后一个指针一次移动一个节点。前一个指针到达尾部时,后一个指针到达中间节点。

反转链表

反转一个单链表,返回它的头节点。

很容易想到的是直接反转,后一个节点指向前一个节点。但是会有一个问题,到为尾节点的时候,会发生链表中断,这是因为尾节点的下一个结点为空。

关键点:要将前一个节点保存下来,所以要使用三个指针

public ListNode reverseListNode(ListNode pHead){
        if(pHead ==null) return null;
        ListNode pNewHead = null;
        ListNode pPre = null;
        ListNode pCur = pHead;
        
        while(pCur !=null){
            ListNode pNext = pCur.next;
            if(pNext == null){  //找到新的头节点
                pNewHead = pCur;  
            }
            pCur.next = pPre;  //反转
            pPre = pCur;
            pCur = pNext;
            
        }
        return pNewHead;
    }

是否可以想到添加一个指针来保存之前的节点是解题的关键

推荐阅读更多精彩内容