程序员面试金典:面试题 02.01~02.06

面试题 02.01. 移除重复节点

编写代码,移除未排序链表中的重复节点。保留最开始出现的节点。

示例1:

 输入:[1, 2, 3, 3, 2, 1]
 输出:[1, 2, 3]

思路:

  • 若使用额外内存空间,将节点保存在set中,如果当前节点值已经存在于set中,则移除该节点
class Solution {
    public ListNode removeDuplicateNodes(ListNode head) {
        if (head == null) {
            return head;
        }
        Set<Integer> set = new HashSet<>();
        ListNode pre = head;
        set.add(head.val);//放入头节点的值
        while (pre.next != null) {
            ListNode cur = pre.next;
            if (set.add(cur.val)) {
                pre = pre.next;
            } else {
                pre.next = pre.next.next;
            }
        }
        return head;
    }
}
  • 不适用额外空间,则需要两层for循环,依次比较当前节点的值与其后面的n-i个值是否重复,若重复,则移除
class Solution {
    public ListNode removeDuplicateNodes(ListNode head) {
        if (head == null) {
            return head;
        }
        ListNode cur = head;
        while (cur != null) {
            ListNode temp = cur;
            while (temp.next != null) {
                if (temp.next.val == cur.val) {
                    temp.next = temp.next.next;
                } else {
                    temp = temp.next;
                }
            }
            cur = cur.next;
        }
        return head;
    }
}

面试题 02.02. 返回倒数第 k 个节点

实现一种算法,找出单向链表中倒数第 k 个节点。返回该节点的值。

示例:

输入: 1->2->3->4->5 和 k = 2
输出: 4

思路:两个节点,fast节点 先走到第k个节点,之后slow节点和fast节点一起遍历,当fast节点为null时,返回slow节点的值即可。

class Solution {
    public int kthToLast(ListNode head, int k) {
        ListNode fast = head;
        while (k-- > 0) {
            fast = fast.next;
        }
        ListNode slow = head;
        while (fast != null) {
            slow = slow.next;
            fast = fast.next;
        }
        return slow.val;
    }
}

面试题 02.04. 分割链表

给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。

你不需要 保留 每个分区中各节点的初始相对位置。

示例 1:

输入:head = [1,4,3,2,5,2], x = 3
输出:[1,2,2,4,3,5]

思路:根据给出的值x,将链表分为两个链表,小于x的为一个链表small,大于等于x的为另一个链表big,之后将big链表连接到small链表后面即可

class Solution {
    public ListNode partition(ListNode head, int x) {
        if (head == null) {
            return head;
        }
        ListNode dummySmall = new ListNode(0);
        ListNode dummyBig = new ListNode(0);
        ListNode curSmall = dummySmall, curBig = dummyBig;
        ListNode cur = head;
        while (cur != null) {
            if (cur.val < x) {
                curSmall.next = cur;
                curSmall = curSmall.next;
            } else {
                curBig.next = cur;
                curBig = curBig.next;
            }
            cur = cur.next;
        }
        curSmall.next = dummyBig.next;
        curBig.next = null;
        return dummySmall.next;
    }
}

面试题 02.05. 链表求和

给定两个用链表表示的整数,每个节点包含一个数位。这些数位是反向存放的,也就是个位排在链表首部。编写函数对这两个整数求和,并用链表形式返回结果。

示例:

输入:(7 -> 1 -> 6) + (5 -> 9 -> 2),即617 + 295
输出:2 -> 1 -> 9,即912

思路:由于是反向存放,所以可以直接对应位相加即可。

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode p1 = l1, p2 = l2;
        ListNode dummy = new ListNode(0);
        ListNode cur = dummy;
        int jinwei = 0;
        //当p1,p2都为null且进位为0时,才退出for循环
        while (p1 != null || p2 != null || jinwei != 0) {
            int x = 0;
            int y = 0;
            if (p1 != null) {
                x = p1.val;
                p1 = p1.next;
            }
            if (p2 != null) {
                y = p2.val;
                p2 = p2.next;
            }
            int temp = x + y + jinwei;
            cur.next = new ListNode(temp % 10);
            cur = cur.next;
            jinwei = temp / 10;
        }
        return dummy.next;
    }
}

进阶:思考一下,假设这些数位是正向存放的,又该如何解决呢?

思路:可以先将每个链表翻转,之后相加得到一个链表,在对得到的这个链表翻转即可。

面试题 02.06. 回文链表

编写一个函数,检查输入的链表是否是回文的。

思路:将链表根据int mid = (length + 1) / 2;拆分为两部分,将后半部分组成的新链表翻转,指定两个指针,依次比较两个链表中相同位置的节点的值是否相等。

class Solution {
    public boolean isPalindrome(ListNode head) {
        if (head == null || head.next == null) {
            return true;
        }
        int length = 0;
        ListNode cur = head;
        while (cur != null) {
            length++;
            cur = cur.next;
        }
        int mid = (length + 1) / 2;
        cur = head;
        while (mid-- > 0) {
            cur = cur.next;
        }
        ListNode p2 = cur;
        p2 = reverse(p2);
        cur.next = null;
        cur = head;
        while (p2 != null) {
            if (p2.val != cur.val) {
                return false;
            }
            p2 = p2.next;
            cur = cur.next;
        }
        return true;
    }
    private ListNode reverse(ListNode node) {
        ListNode pre = null;
        ListNode cur = node;
        while (cur != null) {
            ListNode temp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = temp;
        }
        return pre;
    }
}
posted @ 2022-05-19 12:00  Arthurma  阅读(24)  评论(0编辑  收藏  举报