Cracking the Coding Interview - Summary


https://www.bbsmax.com/A/D854p0w5Eg/
第18章---高度难题

1,-------另类加法。实现加法。
  1. 请编写一个函数,将两个数字相加。不得使用+或其他算数运算符。
  2. 给定两个int AB。请返回AB的值
  3. 测试样例:
  4. 1,2
  5. 返回:3
答案和思路:xor是相加不进位。and得到每一个地方的进位。所以,用and<<1之后去与xor异或。不断递归。
    public int addAB(int a, int b) {
        if (b == 0) {
            return a;
        }
        int xor = a ^ b;
        int and = a & b;
        and = and << 1;
        return addAB(xor, and);
    }

第17章中等难度的题

1,--------无缓存交换

请编写一个函数,函数内不使用任何临时变量,直接交换两个数的值。
给定一个int数组AB,其第零个元素和第一个元素为待交换的值,请返回交换后的数组。
测试样例:
[1,2]
返回:[2,1]

答案:注意,用异或来做一定要判断是否相等。不然就是0了。记忆:左边a,b,a,右边都是a^b。

    public int[] exchangeAB(int[] AB) {
        // write code here
        if (AB[0] == AB[1]) {
            return AB;
        }
        AB[0] = AB[0] ^ AB[1];
        AB[1] = AB[0] ^ AB[1];
        AB[0] = AB[0] ^ AB[1];
        return AB;
    }

2,----------井字游戏

题目描述
对于一个给定的井字棋棋盘,请设计一个高效算法判断当前玩家是否获胜。
给定一个二维数组board,代表当前棋盘,其中元素为1的代表是当前玩家的棋子,为0表示没有棋子,为-1代表是对方玩家的棋子。
测试样例:
[[1,0,1],[1,-1,-1],[1,-1,0]]
返回:true

    public boolean checkWon(int[][] board) {
        // write code here
        for (int i = 0; i < 3; ++i) {
            if (board[i][0] == 1 && board[i][1] == 1 && board[i][2] == 1) {
                return true;
            }
        }
        for (int j = 0; j < 3; ++j) {
            if (board[0][j] == 1 && board[1][j] == 1 && board[2][j] == 1) {
                return true;
            }
        }
        if (board[0][0] == 1 && board[1][1] == 1 && board[2][2] == 1) {
            return true;
        }
        if (board[0][2] == 1 && board[1][1] == 1 && board[2][0] == 1) {
            return true;
        }
        return false;
    }

 3,----------阶乘尾0的个数

  1. Factorial Trailing Zeroes My Submissions QuestionEditorial Solution
  2. Total Accepted: 57385 Total Submissions: 175529 Difficulty: Easy
  3. Given an integer n, return the number of trailing zeroes in n!.
  4. Note: Your solution should be in logarithmic time complexity.
  5. Credits:
  6. Special thanks to @ts for adding this problem and creating all test cases.
  7. Subscribe to see which companies asked this question
答案和思路:注意这里面如果i是int会越界导致WA。改为了long

  1. public int trailingZeroes(int n) {
  2. if (n < 0) {
  3. return -1;
  4. }
  5. int count = 0;
  6. for (long i = 5; n / i > 0; i *= 5) {
  7. count += n / i;
  8. }
  9. return count;
  10. }
 4,--------------无判断max

  1. 无判断max
  2. 参与人数:499时间限制:3秒空间限制:32768K
  3. 本题知识点: 编程基础
  4. 算法知识视频讲解
  5. 题目描述
  6. 请编写一个方法,找出两个数字中最大的那个。条件是不得使用if-else等比较和判断运算符。
  7. 给定两个int ab,请返回较大的一个数。若两数相同则返回任意一个
答案和解析:利用好abs
  1. public class Max {
  2. public int getMax(int a, int b) {
  3. return ((a + b) + Math.abs(a - b)) / 2;
  4. }


5,------------珠玑妙算

题目描述
我们现在有四个槽,每个槽放一个球,颜色可能是红色(R)、黄色(Y)、绿色(G)或蓝色(B)。例如,可能的情况为RGGB(槽1为红色,槽2、3为绿色,槽4为蓝色),作为玩家,你需要试图猜出颜色的组合。比如,你可能猜YRGB。要是你猜对了某个槽的颜色,则算一次“猜中”。要是只是猜对了颜色但槽位猜错了,则算一次“伪猜中”。注意,“猜中”不能算入“伪猜中”。
给定两个string A和guess。分别表示颜色组合,和一个猜测。请返回一个int数组,第一个元素为猜中的次数,第二个元素为伪猜中的次数。
测试样例:
"RGBY","GGRR"
返回:[1,1]c

答案和思路:猜中的话直接来统计。顺便建立list。

    public int[] calcResult(String A, String B) {
        int[] res = new int[2];
        if (A == null || A.length() == 0 || B == null || B.length() == 0) {
            return res;
        }
        ArrayList<Character> listA = new ArrayList(); // use set
        ArrayList<Character> listB = new ArrayList();
        for (int i = 0; i < A.length(); ++i) {
            if (A.charAt(i) == B.charAt(i)) {
                res[0]++;
            }
            listA.add(A.charAt(i));
            listB.add(B.charAt(i));
        }
        for(Character c : listB) {
            if (listA.contains(c)) {
                res[1]++;
                listA.remove(c);
            }
        }
        res[1] -= res[0];
        return res;
    }

8,---------最大的连续和

最大连续数列和
参与人数:425时间限制:3秒空间限制:32768K
本题知识点: 贪心
 算法知识视频讲解
题目描述
对于一个有正有负的整数数组,请找出总和最大的连续数列。
给定一个int数组A和数组大小n,请返回最大的连续数列的和。保证n的大小小于等于3000。
测试样例:
[1,2,3,-6,1]
返回:6

答案和思路:dp[i] 表示以i为结尾的最大和。用max记录最大的。

    public int getMaxSum(int[] A, int n) {
        // write code here
        if (A == null || A.length == 0) {
            return 0;
        }
        int max = A[0];
        int[] dp = new int[A.length];
        dp[0] = A[0];
        for (int i = 1; i < A.length; ++i) {
            if (dp[i - 1] > 0) {
                dp[i] = A[i] + dp[i - 1];
            } else {
                dp[i] = A[i];
            }
            max = Math.max(max, dp[i]);
        }
        return max;
    }
11,-------------随机数构造。rand5() => rand7()

思路:randN() => randM()。

rangdN()*N + randN()。这样的话就能一直是等概率的产生。条件一前面的加起来要大于randM()。然后只取他的整数倍。之所以*N,是因为为了+randN()的时候,刚好能放进去0,1,...,N-1.

    while (true) {
        int num = rand5() * 5 + rand5();
        if (num < 21) {
            return num % 7;
        }
    }

 7.1,投篮球,玩法一:一次出手。玩法二:投三次,必须投中两次才算赢。假设投中概率是p

p1 = p;  p2 = 3 * p * p * (p - 1); 

算什么情况下选玩法一:p1 > p2.求得p < 0.5的时候。p > 0.5选第二种。但是p = 0, 1, 0.5两种都是一样的。



7.2,碰撞的蚂蚁,多边形上多个蚂蚁

碰撞的蚂蚁
参与人数:523时间限制:3秒空间限制:32768K
 算法知识视频讲解
题目描述
在n个顶点的多边形上有n只蚂蚁,这些蚂蚁同时开始沿着多边形的边爬行,请求出这些蚂蚁相撞的概率。(这里的相撞是指存在任意两只蚂蚁会相撞)
给定一个int n(3<=n<=10000),代表n边形和n只蚂蚁,请返回一个double,为相撞的概率。
测试样例:
3
返回:0.75

答案:求不不可能碰撞的情况,就是同向。

    public double antsCollision(int n) {
        // write code here
        return (1 - Math.pow(0.5, n - 1));
    }

7.3,判断直线是否相交

判断直线相交
参与人数:490时间限制:3秒空间限制:32768K
 算法知识视频讲解
题目描述
给定直角坐标系上的两条直线,确定这两条直线会不会相交。
线段以斜率和截距的形式给出,即double s1,double s2,double y1,double y2,分别代表直线1和2的斜率(即s1,s2)和截距(即y1,y2),请返回一个bool,代表给定的两条直线是否相交。这里两直线重合也认为相交。
测试样例:
3.14,1,3.14,2
返回:false

答案:

import java.util.*;
public class CrossLine {
    public boolean checkCrossLine(double s1, double s2, double y1, double y2) {
        // write code here
        if (y1 == y2) {
            return true;
        }
        if (s1 == s2) {
            return false;
        }
        return true;
    }
}

7.4,只使用加好来算乘法,除法,减法。

加法运算替代
参与人数:445时间限制:3秒空间限制:32768K
本题知识点: 编程基础
 算法知识视频讲解
题目描述
请编写一个方法,实现整数的乘法、减法和除法运算(这里的除指整除)。只允许使用加号。
给定两个正整数int a,int b,同时给定一个int type代表运算的类型,1为求a * b,0为求a / b,-1为求a - b。请返回计算的结果,保证数据合法且结果一定在int范围内。
测试样例:
1,2,1
返回:2

答案:关键部分就是引入一个取反的函数negate

import java.util.*;
public class AddSubstitution {
    public int calc(int a, int b, int type) {
        int result = 0;
        if (type == 1) {
            result = multiply(a, b);
        } else if (type == 0) {
            result = divide(a, b);
        } else {
            result = minus(a, b);
        }
        return result;
    }
    private static int negate(int a) {
        int neg = 0;
        int d = a > 0 ? -1 : 1;
        for (int i = 0; i * i < a * a; i++) {
            neg += d;
        }
        return neg;
    }
    private static int minus(int a, int b) {
        int negB = negate(b);
        return a + negB;
    }
    private static int multiply(int a, int b) {
        int result = 0;
        for (int i = 0; i * i < a * a; ++i) {
            result += b;
        }
        if (a < 0 && b > 0 || a > 0 && b < 0) {
            result = negate(result);
        }
        return result;
    }
    private static int divide(int a, int b) {
        if (b > a) {
            return 0;
        }
        int result = 0;
        int a1 = a > 0 ? a : negate(a);
        int b1 = b > 0 ? b : negate(b);
        int sum = b1;
        while (sum <= a1) {
            result++;
            sum += b1;
        }
        if (a > 0 && b < 0 || a < 0 && b > 0) {
            result = negate(result);
        }
        return result;
    }
}



7.5,平分的直线

平分的直线
参与人数:296时间限制:3秒空间限制:32768K
 算法知识视频讲解
题目描述
在二维平面上,有两个正方形,请找出一条直线,能够将这两个正方形对半分。假定正方形的上下两条边与x轴平行。
给定两个vecotrA和B,分别为两个正方形的四个顶点。请返回一个vector,代表所求的平分直线的斜率和截距,保证斜率存在。
测试样例:
[(0,0),(0,1),(1,1),(1,0)],[(1,0),(1,1),(2,0),(2,1)]
返回:[0.0,0.5]

答案和知识点:注意要划分一个正方形的线,只要过中心就可以了。然后做题的时候注意一下。到底是哪个点减去哪个点得到中心。因为给的点顺序不一定相同。

import java.util.*;
/*
public class Point {
    int x;
    int y;
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
    public Point() {
        this.x = 0;
        this.y = 0;
    }
}*/
public class Bipartition {
    public double[] getBipartition(Point[] a, Point[] b) {
        // write code here
        double[][] center = new double[2][2];
        center[0][0] = (a[1].x + a[0].x) / 2.0;
        center[0][1] = (a[3].y + a[0].y) / 2.0;
        center[1][0] = (b[1].x + b[0].x) / 2.0;
        center[1][1] = (b[3].y + b[0].y) / 2.0;
        double[] result = new double[2];
        result[0] = (center[1][1] - center[0][1]) * 1.0/ (center[1][0] - center[0][0]);
        result[1] = center[0][1] - result[0] * center[0][0];
        return result;
    }
}

 7.6,过直线的点最多。

穿点最多的直线
参与人数:201时间限制:3秒空间限制:32768K
本题知识点: 高级结构 堆 哈希 图 树 队列 栈 链表 字符串 数组 编程基础 复杂度 穷举 模拟 分治 动态规划 贪心 递归 排序 查找
 算法知识视频讲解
题目描述
在二维平面上,有一些点,请找出经过点数最多的那条线。
给定一个点集vector p和点集的大小n,请返回一个vector,代表经过点数最多的那条直线的斜率和截距。

答案和思路:暴力枚举。不过注意要单独写函数来求斜率,截距。单独写函数来判断有多少个点过函数。这里虽然没用到,但是记住double用==是不行的。

import java.util.*;
/*
public class Point {
    int x;
    int y;
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
    public Point() {
        this.x = 0;
        this.y = 0;
    }
}*/
public class DenseLine {
    public double[] getLine(Point[] p, int n) {
        // write code here
        int max = 0;
        double[] result = new double[2];
        for (int i = 0; i < p.length; i++) {
            for (int j = i + 1; j < p.length; ++j) {
               double[] temp = getLine(p[i], p[j]);
                int num = getNum(temp, p);
                if (num > max) {
                    result[0] = temp[0];
                    result[1] = temp[1];
                }
            }
        }
        return result;
    }
    private static double[] getLine(Point a, Point b) {
        double[] result = new double[2];
        result[0] = (a.y - b.y) * 1.0 / (a.x - b.x);
        result[1] = a.y - result[0] * a.x;
        return result;
    }
    private static int getNum(double[] a, Point[] p) {
        int num = 0;
        for (int i = 0; i < p.length; ++i) {
            if (p[i].y == p[i].x * a[0] + a[1]) {
                num++;
            }
        }
        return num;
    }


4.2,有向路径检查。找图的两个节点是否存在路径

对于一个有向图,请实现一个算法,找出两点之间是否存在一条路径。
给定图中的两个结点的指针UndirectedGraphNode* a,UndirectedGraphNode* b(请不要在意数据类型,图是有向图),请返回一个bool,代表两点之间是否存在一条路径(a到b或b到a)。

(1)答案和思路:注意的是这里是一个有向图。所以,要判断a到b还要判断b到a。  注意如何判断图的点是否出现过,可以用hashset来记录已经出现过的点。这是一个小技巧要记住了。然后就是BFS。用queue来做就可以了。

import java.util.*;
/*
public class UndirectedGraphNode {
    int label = 0;
    UndirectedGraphNode left = null;
    UndirectedGraphNode right = null;
    ArrayList<UndirectedGraphNode> neighbors = new ArrayList<UndirectedGraphNode>();
    public UndirectedGraphNode(int label) {
        this.label = label;
    }
}*/
public class Path {
    public boolean checkPath(UndirectedGraphNode a, UndirectedGraphNode b) {
        return checkPath2(a, b) || checkPath2(b, a);
    }
    public static boolean checkPath2(UndirectedGraphNode a, UndirectedGraphNode b) {
        // write code here
        if ( a == b) {
            return true;
        }
        Queue<UndirectedGraphNode> queue = new LinkedList();
        HashSet hash = new HashSet();
        hash.add(a);
        queue.add(a);
        while (!queue.isEmpty()) {
            UndirectedGraphNode top = queue.poll();
            for (UndirectedGraphNode g : top.neighbors) {
                if (g == b) {
                    return true;
                }
                if (!hash.contains(g)) {
                    queue.add(g);
                    hash.add(g);
                }
            }
        }
        return false;
    }
}

 4.3,求建立BST树的高度(附上如何建立一棵BST树)

高度最小的BST
参与人数:715时间限制:3秒空间限制:32768K
本题知识点: 高级结构 树
 算法知识视频讲解
题目描述
对于一个元素各不相同且按升序排列的有序序列,请编写一个算法,创建一棵高度最小的二叉查找树。
给定一个有序序列int[] vals,请返回创建的二叉查找树的高度。

 答案:求高度的答案。利用2^height - 1 = nums; height = nums + 1的log2为低。利用好Math.ceil取上整。

import java.util.*;
public class MinimalBST {
    public int buildMinimalBST(int[] vals) {
        if (vals == null || vals.length == 0) {
            return 0;
        }
        int length = vals.length;
        return (int)Math.ceil(Math.log(length + 1) / Math.log(2));
    }
}

这里是真正建立了一棵树,然后再通过BST树来求高度。

import java.util.*;
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int v) {
        val = v;
        left = null;
        right = null;
    }
}
public class MinimalBST {
    public int buildMinimalBST(int[] vals) {
        if (vals == null || vals.length == 0) {
            return 0;
        }
        int length = vals.length;
        TreeNode root = buildMinimalBST(vals, 0, length - 1);
        return height(root);
    }
    public static TreeNode buildMinimalBST(int[] vals, int start, int end) {
        if (end < start) {
            return null;
        }
        int mid = (start + end) / 2;
        TreeNode n = new TreeNode(vals[mid]);
        n.left = buildMinimalBST(vals, start, mid - 1);
        n.right = buildMinimalBST(vals, mid + 1, end);
        return n;
    }
    private static int height(TreeNode root) {
        if (root == null) {
            return 0;
        }
        return Math.max(height(root.left), height(root.right)) + 1;
    }
}

 4.4,建立树在某一层的链表。

输出单层结点
参与人数:626时间限制:3秒空间限制:32768K
本题知识点: 树
 算法知识视频讲解
题目描述
对于一棵二叉树,请设计一个算法,创建含有某一深度上所有结点的链表。
给定二叉树的根结点指针TreeNode* root,以及链表上结点的深度,请返回一个链表ListNode,代表该深度上所有结点的值,请按树上从左往右的顺序链接,保证深度不超过树的高度,树上结点的值为非负整数且不超过100000。

答案:注意看链表存的是什么,是树节点,还是他的值。另外一个这里只需要建立一层。而另一种需求是所有层都建立。没有Bug-free:没有特判深度是1.

import java.util.*;
/*
public class ListNode {
    int val;
    ListNode next = null;
    ListNode(int val) {
        this.val = val;
    }
}*/
/*
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;
    public TreeNode(int val) {
        this.val = val;
    }
}*/
public class TreeLevel {
    public ListNode getTreeLevel(TreeNode root, int dep) {
        // write code here
        ListNode head = new ListNode(0);
        if (root == null) {
            return head;
        }
        Queue<TreeNode> queue = new LinkedList();
        queue.add(root);
        if (dep == 1) {
            return new ListNode(root.val);
        }
        int height = 1;
        ListNode cur = head;
        while (queue.size() != 0) {
            int size = queue.size();
            if (height == dep - 1) {
               for (int i = 0; i < size; i++) {
                   TreeNode node = queue.poll();
                   if (node.left != null) {
                       cur.next = new ListNode(node.left.val);
                       cur = cur.next;
                   }
                   if (node.right != null) {
                       cur.next = new ListNode(node.right.val);
                       cur = cur.next;
                   }
               }
               break;
            }
            for (int i = 0; i < size; ++i) {
                TreeNode n = queue.poll();
                if (n.left != null) {
                    queue.add(n.left);
                }
                if (n.right != null) {
                    queue.add(n.right);
                }
            }
            height++;
        }
         return head.next;
    }
}

4.6,找中序后继结点

寻找下一个结点
参与人数:595时间限制:3秒空间限制:32768K
本题知识点: 树
 算法知识视频讲解
题目描述
请设计一个算法,寻找二叉树中指定结点的下一个结点(即中序遍历的后继)。
给定树的根结点指针TreeNode* root和结点的值int p,请返回值为p的结点的后继结点的值。保证结点的值大于等于零小于等于100000且没有重复值,若不存在后继返回-1。

答案和思路:记住flag只有是全局变量的时候才会一直被保存。

import java.util.*;
/*
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;
    public TreeNode(int val) {
        this.val = val;
    }
}*/
public class Successor {
    static int result = -1;
    static boolean flag = false;
    public int findSucc(TreeNode root, int p) {
        // write code here
        if (root == null) {
            return -1;
        }
        inOrder(root, p);
        return result;
    }
    private static void inOrder(TreeNode root, int p) {
        if (root == null) {
            return;
        }
        inOrder(root.left, p);
        if (flag) {
            result = root.val;
            flag = false;
        }
        if (root.val == p) {
            flag = true;
        }
        inOrder(root.right, p);
    }
 4.7,找最近公共祖先(LowestCommonAncestor, LCA)

给定一棵二叉树,找到两个节点的最近公共父节点(LCA)。
最近公共祖先是两个节点的公共的祖先节点且具有最大深度。

答案和解析:利用先遇到谁。首先如果root与其中一个相等,或者==null,那么肯定返回root。开始左右递归。left记录左边的先遇到的值。right记录右边先遇到的值。如果一直没有遇到那么为null。当两边都遇到了,那么祖先是上一层。如果只有一边不是null。那么说明遇到他就已经退出了。他就是祖先。

/**
 * Definition of TreeNode:
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left, right;
 *     public TreeNode(int val) {
 *         this.val = val;
 *         this.left = this.right = null;
 *     }
 * }
 */
public class Solution {
    /**
     * @param root: The root of the binary search tree.
     * @param A and B: two nodes in a Binary.
     * @return: Return the least common ancestor(LCA) of the two nodes.
     */
    // public TreeNode lowestCommonAncestor(TreeNode root, TreeNode A, TreeNode B) {
    //     // write your code here
    // }
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode A, TreeNode B) {
        if (root == null || root == A || root == B) {
            return root;
        }
        TreeNode left = lowestCommonAncestor(root.left, A, B);
        TreeNode right = lowestCommonAncestor(root.right, A, B);
        if (left != null && right != null) {
            return root;
        } else if (left != null) {
            return left;
        } else {
            return right;
        }
    }
}

这题,牛客网靠的是满二叉树的LCA:

答案:这题非常简单。只要a,b不等就一直往上退。谁大就让谁变成他父亲,即除以2。一直到它们相等,一直会相遇的。

import java.util.*;
public class LCA {
    public int getLCA(int a, int b) {
        // write code here
        while (a != b) {
            if (a > b) {
                a = a / 2;
            } else {
                b = b / 2;
            }
        }
        return a;
    }

2.1,删除链表中重复的元素。(让链表的每一个元素都只出现一次)

(1)答案和思路:一种是利用hash来看是否出现删除。还有一种是要求不能使用缓冲区,那么就用双指针来删除。

import java.util.HashSet;
class ListNode {
    int val;
    ListNode next;
    ListNode() {
    }
}
public class Main {
    //用hash
    public static void deleteDups(ListNode n) {
        HashSet hash = new HashSet();
        ListNode preHead = new ListNode();
        preHead.next = n;
        while (n != null) {
            if (hash.contains(n.val)) {
                preHead.next = n.next;
            } else {
                hash.add(n.val);
                preHead = n;
            }
            n = n.next;
        }
    }
    //不能够临时缓冲区
    public static void deleteDups2(ListNode head) {
        if (head == null) {
            return;
        }
        ListNode cur = head;
        ListNode fast = head;
        while (cur != null) {
            fast = cur;
            while (fast.next != null) {
                if (fast.next.val == cur.val) {
                    fast.next = fast.next.next;
                } else {
                    fast = fast.next;
                }
            }
        }
        cur = cur.next;
    }
}

 2.2,输入一个链表,输出该链表中倒数第k个结点。

 (1)答案和思路:记得要判断k==0.输出null。不然会报错。

/*
public class ListNode {
    int val;
    ListNode next = null;
    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {
        if (head == null || k <= 0) {
            return null;
        }
        // Error :如果K比length大怎么办要判断
        // Error : k <= 0 也要特殊判断
        ListNode fast = head;
        for (int i = 0; i < k - 1; i++) {
            fast = fast.next;
            if (fast == null) {
                return fast;
            }
        }
        while (fast.next != null) {
            head = head.next;
            fast = fast.next;
        }
        return head;
    }
}

 2.3,删除链表中的某一个结点

实现一个算法,删除单向链表中间的某个结点,假定你只能访问该结点。
给定带删除的节点,请执行删除操作,若该节点为尾节点,返回false,否则返回true

(1)答案和思路:注意可以返回boolean表示是否删除成功,如果是尾结点。设置为:false;

public class Remove {
    public boolean removeNode(ListNode pNode) {
        // write code here
        if (pNode == null || pNode.next == null) {
            return false;
        }
        pNode.val = pNode.next.val;
        pNode.next = pNode.next.next;
        return true;
    }
}

 2.4,链表分割(小于x的在一边。大于等于x的又在一边)

编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前
给定一个链表的头指针 ListNode* pHead,请返回重新排列后的链表的头指针。注意:分割以后保持原来的数据顺序不变。

(1)答案:开两个链表来存一下。注意不要忘记next。然后无论是small还是big的头都是个虚头。这样更方便。

import java.util.*;
/*
public class ListNode {
    int val;
    ListNode next = null;
    ListNode(int val) {
        this.val = val;
    }
}*/
public class Partition {
    public ListNode partition(ListNode pHead, int x) {
        // write code here
        ListNode small = new ListNode(0);
        ListNode big = new ListNode(0);
        ListNode tempSmall = small;
        ListNode tempBig = big;
        while (pHead != null) {
            if (pHead.val < x) {
                tempSmall.next = new ListNode(pHead.val);
                tempSmall = tempSmall.next;
            } else {
                tempBig.next = new ListNode(pHead.val);
                tempBig = tempBig.next;
            }
            //Error: 没有next
            pHead = pHead.next;
        }
        tempSmall.next = big.next;
        return small.next;
    }
}

 2.5,链表相加A+B(链表存的是数位)

有两个用链表表示的整数,每个结点包含一个数位。这些数位是反向存放的,也就是个位排在链表的首部。编写函数对这两个整数求和,并用链表形式返回结果。
给定两个链表ListNode* A,ListNode* B,请返回A+B的结果(ListNode*)。
测试样例:
{1,2,3},{3,2,1}
返回:{4,4,4}

(1)思路和答案:注意最后如果digit还有值要继续新建。

import java.util.*;
/*
public class ListNode {
    int val;
    ListNode next = null;
    ListNode(int val) {
        this.val = val;
    }
}*/
public class Plus {
    public ListNode plusAB(ListNode a, ListNode b) {
        // write code here
        if (a == null) {
            return b;
        }
        if (b == null) {
            return a;
        }
        ListNode preHead = new ListNode(0);
        ListNode cur = preHead;
        int sum = 0;
        int digit = 0;
        while (a != null || b != null) {
            if (a != null && b != null) {
                sum = a.val + b.val + digit;
                digit = sum / 10;
                sum = sum - digit * 10;
                cur.next = new ListNode(sum);
                cur = cur.next;
                a = a.next;
                b = b.next;
            } else if (a != null) {
                sum = a.val + digit;
                digit = sum / 10;
                sum = sum - digit * 10;
                cur.next = new ListNode(sum);
                cur = cur.next;
                a = a.next;
            } else {
                sum = b.val + digit;
                digit = sum / 10;
                sum = sum - digit * 10;
                cur.next = new ListNode(sum);
                cur = cur.next;
                b = b.next;
            }
        }
        //Error: 别忘记如果最后digit还有值的话要判断一下。
        if (digit != 0) {
            cur.next = new ListNode(digit);
        }
        return preHead.next;
    }
}

 2.6,找链表的环的起点

(1)答案和思路:注意的地方就是判断有没有环的时候,要记得写fast == slow break。

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        if (null == head || head.next == null) {
            return null;
        }
        ListNode fast = head;
        ListNode slow = head;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if (fast == slow) {
                break;
            }
        }
        if (fast != slow) {
            return null;
        }
        slow = head;
        while (slow != fast) {
            slow = slow.next;
            fast = fast.next;
        }
        return fast;
    }
}

 2.7,判断链表是否是回文

请编写一个函数,检查链表是否为回文。
给定一个链表ListNode* pHead,请返回一个bool,代表链表是否为回文。
测试样例:
{1,2,3,2,1}
返回:true
{1,2,3,2,3}
返回:false

(1)答案和思路:千万不能试图翻转整个链表来比较。因为那样链表完全被改变了。

然后利用的是翻转后半段链表来比较。注意,fast.next。不要少了一个next。

import java.util.*;
/*
public class ListNode {
    int val;
    ListNode next = null;
    ListNode(int val) {
        this.val = val;
    }
}*/
public class Palindrome {
    public boolean isPalindrome(ListNode pHead) {
        // write code here
        if (pHead == null || pHead.next == null) {
            return true;
        }
        ListNode slow = pHead;
        ListNode fast = pHead;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        ListNode newHead = reverse(slow);
        while (pHead != null && newHead != null) {
            if (pHead.val != newHead.val) {
                return false;
            }
            pHead = pHead.next;
            newHead = newHead.next;
        }
        return true;
    }
    private static ListNode reverse(ListNode head) {
        if (head == null) {
            return null;
        }
        ListNode preHead = new ListNode(0);
        while (head != null) {
            ListNode temp = preHead.next;
            preHead.next = head;
            head = head.next;
            preHead.next.next = temp;
        }
        return preHead.next;
    }
}

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts