面试算法题

排序:选择排序,冒泡排序,快排,堆排,希尔排序

//选择,空间复杂度O(1),时间复杂度为O(n^2)
public static void sort(int[] nums) {
        for (int i = 0; i < nums.length - 1; i++) {
            for (int j = i + 1; j < nums.length; j++) {
                if (nums[i] > nums[j]) {
                    int tmp = nums[j];
                    nums[j] = nums[i];
                    nums[i] = tmp;
                }
            }
        }
    }

//冒泡,空间复杂度O(1),时间复杂度为O(n^2)
public static void sort(int[] nums) {
        for (int i = 0; i < nums.length; i++) {
            for (int j = i; j < nums.length - i - 1; j++) {
                if (nums[j] > nums[j + 1]) {
                    int tmp = nums[j];
                    nums[j] = nums[j + 1];
                    nums[j + 1] = tmp;
                }
            }
        }
    }

//快速排序是一种不稳定的排序方法。空间复杂度O(logn) 或 O(n)
//时间复杂度O(nlogn) 或者 O(n^2) 
public static void sort(int[] nums, int low, int hight) {
        int left = low;
        int right = hight;
        int key = nums[left];
        while (left < right) {
            // 先从右往左找到比key小的,有的话就放到key的位置上,当前这个位置后面就可以进行覆盖
            while (left < right && nums[right] >= key) {
                right--;
            }
            nums[left] = nums[right];
            // 再从左往右找到比key大的数,覆盖到刚才那个 right 位上
            while (left < right && nums[left] <= key) {
                left++;
            }
            nums[right] = nums[left];
        }
        nums[left] = key;
        // 排完后,key左边的数都比key小,key右边的数都比key大,然后就可以分别再把key左右部分进行这样排序
        sort(nums, low, left - 1);
        sort(nums, right + 1, hight);
    }

反转链表

public static ListNode reverseList(ListNode head) {
    ListNode pre = null;
    while (null != head) {
        ListNode next = head.next;
        head.next = pre;
        pre = head;
        head = next;
    }
    return pre;
}

// 递归法 1->2->3->4->null
public static ListNode reverseList(ListNode head) {
    if (null == head && head.next == null) {
        return head;
    }
    ListNode newHead = reverseList(head.next);
    head.next.next = head;//head.next不为null
    head.next = null;
    return newHead;
}

删除链表的倒数第N个节点

public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode node = new ListNode(0,head);
        int len = 0;
        while (head != null) {
            len++;
            head = head.next;
        }
        head = node;
        for (int i = 0; i < len-n; i++) {
            head = head.next;
        }
        ListNode next = head.next;
        head.next = next.next;
        next.next = null;
        return node.next;
    }

数组中第K个最大元素

public int findKthLargest(int[] nums, int k) {
        int len = nums.length;
        Arrays.sort(nums);
        return nums[len - k];
    }

翻转数字

static int reverseNum(int num) {
        int res = 0;
        while (num != 0) {
            int i = num % 10;
            res = res * 10 + i;
            num = num / 10;
        }
        return res;
    }

翻转字符串

static String reverseString(String s) {
        char[] chars = s.toCharArray();
        char[] chars2 = new char[chars.length];
        int j = 0;
        for (int i = chars.length - 1; i >= 0; i--) {
            chars2[j] = chars[i];
            j++;
        }
        return new String(chars2);
    }

static String reverseString2(String s) {
        char[] chars = s.toCharArray();
        int n = chars.length;
        int j = chars.length / 2;
        for (int i = 0; i < j; i++) {
            char tmp = chars[i];
            chars[i] = chars[n - 1 - i];
            chars[n - 1 - i] = tmp;
        }
        return new String(chars);
    }

判断回文数,121,1221

public static boolean isPalindrome(int k) {
        String string = String.valueOf(k);
        int len = string.length();
        int mid = len / 2;
        for (int i = 0; i <= mid; i++) {
            char c1 = string.charAt(i);
            char c2 = string.charAt(len - 1 - i);
            if (c1 != c2) {
                return false;
            }
        }
        return true;
    }

public static boolean isPalindrome2(int x) {
        if (x < 0) return false;
        int div = 1;
        while (x / div >= 10) {
            div = div * 10;
        }
        while (x > 0) {
            int n1 = x % 10;//个位数
            int n2 = x / div;//高位数
            if (n1 != n2) {
                return false;
            }
            x = x % div;//去除高位
            x = x / 10;//去除个位
            div = div / 100;
        }
        return true;
    }

最长回文字符串
判断有效括号,{[()]}

    public static boolean isValid(String s) {
        Stack stack = new Stack<>();
        for (char c : s.toCharArray()) {
            if (c == '{') {
                stack.push('}');
            } else if (c == '[') {
                stack.push(']');
            } else if (c == '(') {
                stack.push(')');
            } else if (stack.isEmpty() || stack.pop() != c) {//不是 {[( 那就一定得是 )]}
                return false;
            }
        }
        return true;
    }

public boolean isValid2(String s) {
        if (s == null || s.length() == 0) return false;
        while (s.contains("{}") || s.contains("[]") || s.contains("()")) {
            s = s.replace("{}", "");
            s = s.replace("()", "");
            s = s.replace("[]", "");
        }
        return s.isEmpty();
    }

括号的分数(())()

//有效的括号的分数 (())()
    public static int score(String s) {
        Stack stack = new Stack<>();
        stack.push(0);
        for (char c : s.toCharArray()) {
            if (c == '(') {
                stack.push(0);
            } else {
                int v1 = stack.pop();
                int v2 = stack.pop();
                stack.push(v2 + Math.max(1, v1 * 2));
            }
        }
        return stack.pop();
    }

括号分数升级版 {()}()[]
最长有效括号
判断链表是否有环

public static boolean hasCycle(ListNode node) {
        Set set = new HashSet<>();
        while (node != null) {
            boolean sus = set.add(node);
            if (!sus) {//HashSet有重复的添加会返回false
                return true;
            }
            node = node.next;
        }
        return false;
    }

//判断是否是环链,快慢指针
    private static boolean hasCycle2(ListNode head) {
        if (head == null || head.getNext() == null) {
            return false;
        }
        ListNode slow = head;
        ListNode fast = head.getNext();
        while (slow != fast) {
            if (fast == null || fast.getNext() == null) {
                return false;
            }
            slow = slow.getNext();
            fast = fast.getNext().getNext();
        }
        return true;
    }

二叉树前序,中序,后序遍历

public void preOrder(ListNode node) {
        if (node == null) return;
        System.out.println(node.getVal());
        preOrder(node.left);
        preOrder(node.right);
    }

public void inOrder(ListNode node) {
        if (node == null) return;
        inOrder(node.left);
        System.out.println(node.getVal());
        inOrder(node.right);
    }

public void postOrder(ListNode node) {
        if (node == null) return;
        postOrder(node.left);
        postOrder(node.right);
        System.out.println(node.getVal());
    }

层序遍历

public static void levelSort(ListNode node) {
        Queue queue = new LinkedList<>();
        queue.add(node);
        int size = queue.size();

        StringBuilder levelPath = new StringBuilder();
        while (!queue.isEmpty()) {
            size--;
            ListNode n = queue.remove();
            levelPath.append(n.getVal().toString());
            if (n.left != null) {
                queue.add(n.left);
            }
            if (n.right != null) {
                queue.add(n.right);
            }
            if (size == 0) {
                size = queue.size();
                System.out.println(levelPath.toString());
                levelPath = new StringBuilder();
            }
        }
    }

打印所有树路径

public static void printAllPath(ListNode node) {
        Queue queue = new LinkedList<>();
        queue.add(node);

        Queue pathQ = new LinkedList<>();
        pathQ.add(node.getVal().toString());

        List pathList = new ArrayList<>();
        while (!queue.isEmpty()) {
            ListNode n = queue.remove();
            String path = pathQ.remove();
            
            if (n.left == null && n.right == null) {
                pathList.add(path);//叶子节点
            } else {
                if (n.left != null) {
                    queue.add(n.left);
                    pathQ.add(path + n.left.val);
                }
                if (n.right != null) {
                    queue.add(n.right);
                    pathQ.add(path + n.right.val);
                }
            }
        }

        System.out.println(pathList.toString());
    }

一个字符串里最长不重复子串
一个字符串里最长不重复子串的长度
最大连续数之和
最大子序和
买卖股票的最佳时机
不用Math函数实现开根
接雨水
数组里两数之和等于给定的值

static int[] twoNumSum(int[] nums, int target) {
        for (int i = 0; i < nums.length - 1; i++) {
            for (int j = i + 1; j < nums.length; j++) {
                if (nums[i] + nums[j] == target) {
                    return new int[]{nums[i], nums[j]};
                }
            }
        }
        return new int[]{};
    }

static int[] twoNumSum2(int[] nums, int target) {
        Map map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            Integer num = target - nums[i];
            Integer n = map.get(num);
            if (n != null) {
                return new int[]{nums[i], n};
            } else {
                map.put(nums[i], nums[i]);
            }
        }
        return new int[]{};
    }

三数之和

public static void threeSum(int[] nums, int k) {
        if (nums == null || nums.length < 3) {
            return;
        }
        Arrays.sort(nums);
        for (int i = 0; i < nums.length - 2; i++) {
            int target = k - nums[i];
            int left = i + 1;
            int right = nums.length - 1;
            while (left < right) {
                if (nums[left] + nums[right] == target) {
                    System.out.println(nums[i] + "+" + nums[left] + "+" + nums[right] + "=" + k);
                    break;
                } else if (nums[left] + nums[right] > target) {
                    right--;
                } else {
                    left++;
                }
            }
        }
    }

柱形图最大面积
最大矩形面积
最大正方形面积
二分查找法

//时间复杂度O(log2n)
static int binarySerach(int[] nums, int key) {
        Arrays.sort(nums);
        int left = 0;
        int right = nums.length-1;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (key > nums[mid]) {
                left = mid + 1;
            } else if (key < nums[mid]) {
                right = mid - 1;
            } else {
                return mid;
            }
        }
    }

爬楼梯
将两个升序链表合并为一个新的 升序 链表并返回
两线程分别打印奇偶数
三线程顺序打印ABC
10个线程打印1~100,打印要从小到大
字符串转数值
环形数组,数组里从第n个位置开始往往后移动,n最终到数组的第一位置
LinkedHashMap 实现 LRU
滑动窗口代码实现
漏桶、令牌桶代码实现
分发糖果
不用Math函数开根

设计个抢红包算法

你可能感兴趣的:(面试算法题)