算法30道

文章目录


1、一个递增二维数组找目标值
2、字符串的替换:每个空格替换成“%20”
3、链表反转
4、输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树
5、数组的旋转:输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
6、斐波那契数列的第n项
7、青蛙跳台阶问题
8、输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
9、一个数组,使得所有的奇数位于数组的前半部分,并保证奇数和奇数位置不变,偶数同理
10、输入一个链表,输出该链表中倒数第k个结点
11、输入一个链表,反转链表后,输出新链表的表头
12、两个单调递增的链表,输出两个链表合成后的链表
13、输入两棵二叉树A,B,判断B是不是A的子结构
14、操作给定的二叉树,将其变换为源二叉树的镜像
15、在一个排序的链表中,删除重复结点,重复的不保留
16、输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序
17、二叉树的层序遍历
18、判断该数组是不是某二叉搜索树的后序遍历的结果
19、输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径
20、输入一个字符串,按字典序打印出该字符串中字符的所有排列
21、数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字
22、topK问题:输入n个整数,找出其中最小的K个数
23、输入两个链表,找出它们的第一个公共结点。
24、输入一棵二叉树,求该树的深度
25、一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字
26、子串划分,子串逆置(“student. a am I“)
27、请实现一个函数按照之字形打印二叉树
28、给定一棵二叉搜索树,请找出其中的第k小的结点
29、ABC三个线程交替打印ABCABC…
30、字符串解码 Decode String(3[a]2[bc])
31、一个链表,奇数位置是升序,偶数位置是降序,返回一个排好序的链表
32、全排列问题,DFS
33、基于递归与回溯实现。全排列1,2,3

1、一个递增二维数组找目标值

//每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序
    public boolean find(int target, int[][] arr) {
        if (arr == null || arr.length == 0) {
            return false;
        }
        int i = 0;
        int j = arr.length - 1;
        while (i < arr.length && j >= 0) {
            if (target < arr[i][j]) {
                j--;
            } else if (target > arr[i][j]) {
                i++;
            } else {
                return true;
            }
        }
        return false;
    }

2、字符串的替换:每个空格替换成“%20”

    public static String replaceSpace(StringBuffer str) {
        int count = 0;
        for (int i = 0; i < str.length(); i++) {
            if (str.charAt(i) == ' ') {
                count++;
            }
        }
        int news_length = str.length() + 2 * count;
        int old_end = str.length() - 1;
        int new_end = news_length - 1;
        str.setLength(news_length);
        while (old_end >= 0 && new_end >= 0) {
            if (str.charAt(old_end) == ' ') {
                str.setCharAt(new_end--, '0');
                str.setCharAt(new_end--, '2');
                str.setCharAt(new_end--, '%');
                --old_end;
            } else {
                str.setCharAt(new_end--, str.charAt(old_end));
                --old_end;
            }
        }
        return str.toString();
    }

3、链表反转

    public static class ListNode {
        int val;
        ListNode next = null;

        ListNode(int val) {
            this.val = val;
        }
    }
	//方法一:stack方式
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        Stack<Integer> stack = new Stack<>();
        while (listNode != null) {
            stack.push(listNode.val);
            listNode = listNode.next;
        }
        ArrayList<Integer> arrayList = new ArrayList<>();
        while (!stack.empty()) {
            arrayList.add(stack.pop());
        }
        return arrayList;
    }
    //方法二,逆置数组
     public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        ArrayList<Integer> list = new ArrayList<>();
        while (listNode != null) {
            list.add(listNode.val);
            listNode = listNode.next;
        }
        int i = 0;
        int j = list.size() - 1;
        while (i < j) {
            Integer temp = list.get(i);
            list.set(i, list.get(j));
            list.set(j, temp);
            i++;
            j--;
        }
        return list;
    }
    //测试
        ListNode a1 = new ListNode(1);
        ListNode a2 = new ListNode(2);
        ListNode a3 = new ListNode(3);
        ListNode a4 = new ListNode(4);
        ListNode a5 = new ListNode(5);
        a1.next = a2;
        a2.next = a3;
        a3.next = a4;
        a4.next = a5;

4、输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树

   public class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;

        TreeNode(int x) {
            val = x;
        }
    }
    public TreeNode reConstructBinaryTree(int[] pre, int[] in) {
        if (pre.length == 0 || in.length == 0) {
            return null;
        }
        return reConstructBinaryTreeCore(pre, 0, pre.length - 1, in, 0, in.length - 1);
    }

    public TreeNode reConstructBinaryTreeCore(int[] pre, int preStart, int preEnd, int[] in, int inStart, int inEnd) {
        if (preStart > preEnd || inStart > inEnd) {
            return null;
        }
        TreeNode root = new TreeNode(pre[preStart]);
        int i = inStart;
        for (; i <= inEnd; i++) {
            if (in[i] == pre[preStart]) {
                root.left = reConstructBinaryTreeCore((pre,preStart+1, i- inStart+preStart, in, inStart, i-1);
                root.right = reConstructBinaryTreeCore((pre, i- inStart+preStart+1,preEnd, in, i+1, inEnd);
                break;
            }
        }
        return root;
    }

5、数组的旋转:输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。

	//方法一:类似于冒泡排序
    public int minNumberInRotateArray(int[] array) {
        if (array == null || array.length == 0) {
            return 0;
        }
        for (int i = 0; i < array.length - 1; i++) {
            if (array[i] > array[i + 1]) {
                return array[i + 1];
            }
        }
        return array[0];
    }
    //方法二:二分
    public int minNumberInRotateArray(int[] array) {
        int low = 0;
        int high = array.length - 1;
        while (low < high) {
            int mid = low + (high - low) / 2;
            if (array[mid] > array[high]) {
                //出现这种情况的array类似[3,4,5,6,0,1,2],此时最小数字一定在mid的右边。
                //low = mid + 1
                low = mid + 1;
            } else if (array[mid] == array[high]) {
                //出现这种情况的array类似 [1,0,1,1,1] 或者[1,1,1,0,1],此时最小数字不好判断在mid左边
                //还是右边,这时只好一个一个试
                high = high - 1;
            } else {
                //出现这种情况的array类似[2,2,3,4,5,6,6],此时最小数字一定就是array[mid]或者在mid的左
                //边。因为右边必然都是递增的。
                //high = mid
                high = mid;
            }
        }
        return array[low];
    }

6、斐波那契数列的第n项

    public int Fibonacci(int n) {
        if (n == 0) {
            return 0;

        }
        int first = 1;
        int second = 1;
        int third = 1;
        while (n > 2) {
            third = first + second;
            first = second;
            second = third;
            --n;
        }
        return third;
    }

7、青蛙跳台阶问题

	//方法一:动规实现
    public int JumpFloor(int target) {
        int[] dp = new int[target + 1];
        dp[0] = 1;
        dp[1] = 1;
       
        for (int i = 2; i <= target; i++) {
            dp[i] = dp[i - 1] + dp[i - 2];
        }
        return dp[target];
    }
    //方法二:
    public int JumpFloor(int target) {
        int first = 1;
        int second = 2;
        int third = target;
        while (target > 2) {
            third = first + second;
            first = second;
            second = third;
            --target;
        }
        return third;
    }

8、输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

    public int NumberOf1(int n) {
        int count = 0;
        while (n != 0) {
            n &= (n - 1);
            count++;
        }
        return count;
    }

9、一个数组,使得所有的奇数位于数组的前半部分,并保证奇数和奇数位置不变,偶数同理

	//插入排序的思想
    public void reOrderArray(int[] array) {
        int k = 0;
        for (int i = 0; i < array.length; i++) {
            if ((array[i] >> 1) == 1) {
                int temp = array[i];
                int j = i;
                while (j > k) {
                    array[j] = array[j - 1];
                    j--;
                }
                array[k++] = temp;
            }
        }
    }

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

    public ListNode FindKthToTail(ListNode head, int k) {
        ListNode head1 = head;
        while (k > 0) {
            head1 = head1.next;
            k--;
        }
        while (head1.next != null) {
            head = head.next;
            head1 = head1.next;
        }
        return head;
    }

11、输入一个链表,反转链表后,输出新链表的表头

	//方法一:三指针
   public ListNode ReverseList(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        //4-5-6
        ListNode first = head;
        ListNode sencond = head.next;
        ListNode third = sencond.next;
        while (third != null) {
            sencond.next = first;
            first = sencond;
            sencond = third;
            third = third.next;
        }
        sencond.next = first;//当上面翻转完毕或者只有两个节点的时候,处理一下,翻转一下
        head.next = null;//设置一下第一个节点的指向null
        head = sencond;//头节点指向最后一个节点
        return head;
    }
    //方法二:头插法
     public ListNode ReverseList1(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode new_head = null;
        while (head != null) {
            ListNode pre = head;
            head = head.next;
            pre.next = new_head;
            new_head = pre;
        }
        return head;
    }
   

12、两个单调递增的链表,输出两个链表合成后的链表

    public ListNode Merge(ListNode list1, ListNode list2) {
        if (list1 == null) {
            return list2;
        }
        if (list2 == null) {
            return list1;
        }
        if (list1.val > list2.val) {
            list1.next = Merge(list1.next, list2);
            return list1;
        } else {
            list2.next = Merge(list1, list2.next);
            return list2;
        }
    }

13、输入两棵二叉树A,B,判断B是不是A的子结构

   public boolean IsSameFromBegin(TreeNode begin, TreeNode beginSub) {
        if (begin == null || beginSub == null) {
            return false;
        }
        if (HasSubtree(begin, beginSub)) {
            return true;
        }
        return IsSameFromBegin(begin.left, beginSub) || IsSameFromBegin(begin.right, beginSub);
    }

    public boolean HasSubtree(TreeNode root1, TreeNode root2) {
        if (root2 == null) {
            return true;
        }
        if (root1 == null) {
            return false;
        }
        if (root1.val != root2.val) {
            return false;
        }
        return HasSubtree(root1.left, root2.left) && HasSubtree(root1.right, root2.right);
    }

14、操作给定的二叉树,将其变换为源二叉树的镜像。

    public void Mirror(TreeNode root) {
        if (root == null) {
            return;
        }
        TreeNode temp = root.left;
        root.left = root.right;
        root.right = temp;
        Mirror(root.left);
        Mirror(root.right);
    }

15、在一个排序的链表中,删除重复结点,重复的不保留

    public ListNode deleteDuplication(ListNode pHead) {
        if (pHead == null) {
            return null;
        }
        ListNode newNode = new ListNode(-1);
        pHead.next = newNode;
        ListNode pre = newNode;
        ListNode last = pHead;
        while (last != null) {
            //不重复的时候直接往下走
            while (last.next != null && last.val != last.next.val) {
                last = last.next;
                pre = pre.next;
            }
            //重复的情况
            while (last.next != null && last.val == last.next.val) {
                last = last.next;
            }
            if (pre.next != last) {
                pre.next = last.next;
            }
            last = last.next;
        }
        return newNode.next;
    }

16、输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。

	public boolean IsPopOrder(int[] pushA, int[] popA) {
        if (pushA == null || pushA.length == 0 || popA == null || popA.length == 0) {
            return false;
        }
        Stack<Integer> stack = new Stack<>();
        int popAi = 0;
        int pushAi = 0;
        stack.push(pushA[pushAi]);
        while (popAi < popA.length && pushAi < pushA.length) {
            if (!stack.isEmpty() && stack.peek() == popA[popAi]) {
                popAi++;
                stack.pop();
            } else if (pushAi < pushA.length) {
                stack.push(pushAi);
            } else {
                break;
            }
        }
        if (stack.empty()) {
            return true;
        } else {
            return false;
        }
    }

17、二叉树的层序遍历

   public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
        if (root == null) {
            return new ArrayList<>();
        }
        Queue<TreeNode> queue = new LinkedList<>();
        ArrayList<Integer> result = new ArrayList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            TreeNode father = queue.poll();
            result.add(father.val);
            if (father.left != null) {
                queue.offer(father.left);
            }
            if (father.right != null) {
                queue.offer(father.right);
            }
        }
        return result;
    }

18、判断该数组是不是某二叉搜索树的后序遍历的结果

    public boolean VerifySquenceOfBST(int[] sequence) {
        if (sequence.length == 0) {
            return false;
        }
        return VerifySquenceOfBSTCore(sequence, 0, sequence.length - 1);
    }

    public boolean VerifySquenceOfBSTCore(int[] sequence, int start, int end) {
        if (start >= end) {
            return true;
        }
        int root = sequence[end];
        int i = 0;
        while (i < end && sequence[i] > root) {
            i++;
        }
        for (int j = i; j < end; j++) {
            if (sequence[j] < root) {
                return false;
            }
        }
        return VerifySquenceOfBSTCore(sequence, 0, i - 1) && VerifySquenceOfBSTCore(sequence, i, end - 1);
    }

19、输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径

	//DFS回溯
    public ArrayList<ArrayList<Integer>> FindPath(TreeNode root, int target) {
        ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
        ArrayList<Integer> list = new ArrayList<>();
        FindPathDFS(root, target, result, list);
        return result;
    }

    public void FindPathDFS(TreeNode root, int target, ArrayList<ArrayList<Integer>>
            result, ArrayList<Integer> list) {
        if (root == null) {
            return;
        }
        list.add(root.val);
        target -= root.val;
        if (root.left == null && root.right == null && target == 0) {
            result.add(new ArrayList<Integer>(list));
        }
        FindPathDFS(root.left, target, result, list);
        FindPathDFS(root.right, target, result, list);
        list.remove(list.size() - 1);
    }

20、输入一个字符串,按字典序打印出该字符串中字符的所有排列

	//全排列问题,DFS
    public ArrayList<String> Permutation(String str) {
        ArrayList<String> result = new ArrayList<>();
        if (str != null && str.length() > 0) {
            PermutationHelper(str.toCharArray(), 0, result);
            Collections.sort(result);
        }
        return result;
    }
    public void PermutationHelper(char[] str, int start, ArrayList<String> result) {
        if (start == str.length - 1) {
            if (!IsExist(result, str)) {
                result.add(new String(str));
            }
            return;
        }
        for (int i = start; i < str.length; i++) {
            Swap(str, start, i);
            PermutationHelper(str, start + 1, result);
            Swap(str, start, i);
        }
    }
    public void Swap(char[] str, int i, int j) {
        char temp = str[i];
        str[i] = str[j];
        str[j] = temp;
    }

    public boolean IsExist(ArrayList<String> result, char[] str) {
        return result.contains(String.valueOf(str));
    }

21、数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字

	//定义map,使用<数字,次数>的映射关系,最后统计每个字符出现的次数
    public int MoreThanHalfNum_Solution(int[] array) {
        if (array == null) {
            return 0;
        }
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < array.length; i++) {
            if (map.containsKey(array[i])) {
                int count = map.get(array[i]);
                count++;
                map.put(array[i], count);
            } else {
                map.put(array[i], 1);
            }
            if (map.get(array[i]) > array.length / 2) {
                return array[i];
            }
        }
        return 0;
    }
    //排序,出现次数最多的数字,一定在中间位置。然后检测中间出现的数字出现的次数是否符合要求
     public int MoreThanHalfNum_Solution(int[] array) {
        if (array == null) {
            return 0;
        }
        Arrays.sort(array);
        int target = array[array.length / 2];
        int count = 0;
        for (int i = 0; i < array.length; i++) {
            if (target == array[i]) {
                count++;
            }
        }
        if (count > array.length / 2) {
            return target;
        }
        return 0;
    }
    //目标条件:目标数据超过数组长度的一半,那么对数组,我们同时去掉两个不同的数字,
    //到最后剩 下的一个数就是该数字。如果剩下两个,那么这两个也是一样的,就是结果),
    //在其基础上把最后剩下的一个 数字或者两个回到原来数组中,
    //将数组遍历一遍统计一下数字出现次数进行最终判断。
     public int MoreThanHalfNum_Solution(int[] array) {
        if (array == null) {
            return 0;
        }
        int target = array[0];
        int times = 1;
        for (int i = 1; i < array.length; i++) {
            if (times == 0) {
                target = array[i];
                times = 1;
            } else if (array[i] == target) {
                times++;
            } else {
                times--;
            }
        }
        times = 0;
        for (int i = 0; i < array.length; i++) {
            if (target == array[i]) {
                times++;
            }
        }
        return times > array.length / 2 ? target : 0;
    }

22、topK问题:输入n个整数,找出其中最小的K个数

    public ArrayList<Integer> GetLeastNumbers_Solution(int[] input, int k) {
        ArrayList<Integer> list = new ArrayList<>();
        if (input == null || k <= 0 || k > input.length) {
            return list;
        }
        PriorityQueue<Integer> queue = new PriorityQueue<>(k, Collections.reverseOrder());
        for (int i = 0; i < input.length; i++) {
            if (i < k) {
                queue.offer(input[i]);
            } else {
                if (input[i] < queue.peek()) {
                    queue.poll();
                    queue.offer(input[i]);
                }
            }
        }
        for (int i = 0; i < k; i++) {
            list.add(queue.poll());
        }
        return list;
    }

23、输入两个链表,找出它们的第一个公共结点。

	public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        if (pHead1 == null || pHead2 == null) {
            return null;
        }
        int length1 = GetListLength(pHead1);
        int length2 = GetListLength(pHead2);
        int step = Math.abs(length1 - length2);
        if (length1 > length2) {
            while (step > 0) {
                pHead1 = pHead1.next;
                step--;
            }
        } else {
            while (step > 0) {
                pHead2 = pHead2.next;
                step--;
            }
        }
        while (pHead1 != null && pHead2 != null) {
            if (pHead1 == pHead2) {
                return pHead1;
            }
            pHead1 = pHead1.next;
            pHead2 = pHead2.next;
        }
        return null;
    }

    public int GetListLength(ListNode list) {
        if (list == null) {
            return 0;
        }
        int len = 0;
        while (list != null) {
            len++;
            list = list.next;
        }
        
        return len;
    }

24、输入一棵二叉树,求该树的深度

	//方法一:递归
    public int TreeDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        return Math.max(TreeDepth(root.left), TreeDepth(root.right)) + 1;
    }
    //方法二:层序遍历
    public int TreeDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        Queue<TreeNode> q = new LinkedList<>();
        q.offer(root);
        int depth = 0;
        while (!q.isEmpty()) {
            int size = q.size();
            depth++;
            for (int i = 0; i < size; i++) {
                TreeNode curr = q.poll();
                if (curr.left != null) q.offer(curr.left);
                if (curr.right != null) q.offer(curr.right);
            }
        }
        return depth;
    }

25、一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字

    public void FindNumsAppearOnce(int[] array, int num1[], int num2[]) {
        if (array == null || num1 == null || num2 == null) {
            return;
        }
        num1[0] = 0;
        num2[0] = 0;
        int result = array[0];
        for (int i = 1; i < array.length; i++) {
            result ^= array[i];
        }
        int length = Integer.SIZE;
        int flag = 1;
        while (length >= 0) {
            length -= 1;
            if (((flag << length) & result) != 0) {
                flag <<= length;
                break;

            }
        }
        for (int i = 0; i < array.length; i++) {
            if ((array[i] & flag) == 0) {
                num1[0] ^= array[i];
            } else {
                num2[0] ^= array[i];
            }
        }
    }

26、子串划分,子串逆置(“student. a am I“)

    public String ReverseSentence(String str) {
        if (str == null || str.length() == 0) {
            return str;
        }
        char[] list = str.toCharArray();
        int len = list.length;
        int i = 0;
        int j = i;
        while (i < len) {
            while (i < len && !Character.isSpace(list[i])) i++;
            Reverse(list, j, i - 1);
            while (i < len && Character.isSpace(list[i])) i++;
            j = i;
        }
        Reverse(list, j, i - 1);
        Reverse(list, 0, i - 1);
        return new String(list);
    }

27、请实现一个函数按照之字形打印二叉树

	public ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer>> result = new ArrayList<>();
        if (pRoot == null) {
            return result;
        }
        Stack<TreeNode> st = new Stack<>();
        Queue<TreeNode> q = new LinkedList<>();
        st.push(pRoot);
        int dir = 1;
        ArrayList<Integer> list = new ArrayList<>();
        while (!st.empty()) {
            int size = st.size();
            for (int i = 0; i < size; i++) {
                TreeNode curr = st.pop();
                list.add(curr.val);
                TreeNode first = (dir == 1) ? curr.left : curr.right;
                TreeNode second = (dir == 1) ? curr.right : curr.left;
                if (first != null) q.offer(first);
                if (second != null) q.offer(second);
            }
            result.add(new ArrayList(list));
            list.clear();
            while (!q.isEmpty()) {
                st.push(q.poll());
            }
            dir = (dir == 1) ? 2 : 1;
        }
        return result;
    }

28、给定一棵二叉搜索树,请找出其中的第k小的结点

   TreeNode KthNode(TreeNode pRoot, int k) {
        if (pRoot == null || k <= 0) {
            return null;
        }
        Stack<TreeNode> st = new Stack<>();
        TreeNode node = pRoot;
        do {
            while (node != null) {
                st.push(node);
                node = node.left;
            }
            if (!st.empty()) {
                node = st.pop();
                if (k == 0) {
                    return node;
                }
                node = node.right;
            }
        } while (node != null || !st.empty());
        return null;
    }

29、ABC三个线程交替打印ABCABC...

public class Main extends Thread {

    private volatile static int state = 0;
    private static final String name = "ABC";
    private int type;

    Main(int type) {
        this.type = type;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; ) {//类似自旋锁,不成功就一直重试
            if (state % 3 == type) {
                System.out.println("线程" + type + ":" + name.charAt(type));//type的作用就体现了出来,这里作下标
                state++;
                i++;//成功输出,才可以自增
            }
        }
    }

    public static void main(String[] args) {
        new Main(0).start();//0既可以区分线程,又可以代表我要输出ABC的字符下标是几
        new Main(1).start();
        new Main(2).start();
    }
}

30、字符串解码 Decode String(3[a]2[bc])

 public static String decodeString(String s) {
        int number = 0;
        Stack<Integer> n_Stack = new Stack<>();
        Stack<StringBuffer> w_Stack = new Stack<>();
        StringBuffer val = new StringBuffer();
        for(Character c : s.toCharArray()) {//遍历每一个字符
            if(Character.isDigit(c)) {//判断是否是整形
                number = number*10+c-'0';
            }else if(Character.isLetter(c)) {
                val.append(c);
            }else if(c == '[') {
                n_Stack.push(number);
                number = 0;
                w_Stack.push(val);
                val = new StringBuffer();
            }else {//这种情况"]"的情况
                StringBuffer ss = new StringBuffer();
                ss.append(w_Stack.pop());
                int n = n_Stack.pop();
                for(int i=0;i<n;i++) {
                    ss.append(val);
                }
                val = ss;
            }
        }
        return val.toString();
    }

31、一个链表,奇数位置是升序,偶数位置是降序,返回一个排好序的链表

 	public static void main(String[] args) {
        Main main = new Main();
        ListNode head = main.initList();
        main.printList(head);
        ListNode[] heads = main.splitList(head);
        main.printList(heads[0]);
        main.printList(heads[1]);
        ListNode reverseHead = main.reverseList(heads[1]);
        main.printList(reverseHead);
        ListNode mergeHead = main.mergeLists(heads[0], reverseHead);
        main.printList(mergeHead);
    }

    //按照奇偶位拆分成两个链表
    private ListNode[] splitList(ListNode head) {
        ListNode head1 = null;
        ListNode head2 = null;
        ListNode cur1 = null;
        ListNode cur2 = null;

        int count = 1;
        while (head != null) {
            if (count % 2 == 1) {
                if (cur1 != null) {
                    cur1.next = head;
                    cur1 = cur1.next;
                } else {
                    cur1 = head;
                    head1 = cur1;
                }
            } else {
                if (cur2 != null) {
                    cur2.next = head;
                    cur2 = cur2.next;
                } else {
                    cur2 = head;
                    head2 = cur2;
                }
            }
            head = head.next;
            ++count;
        }
        //跳出循环,要让最后两个末尾元素的下一个都指向null
        cur1.next = null;
        cur2.next = null;
        ListNode[] heads = new ListNode[]{head1, head2};
        return heads;
    }

    //反转链表
    private ListNode reverseList(ListNode head) {
        ListNode cur = head;
        ListNode pre = null;
        ListNode next = null;
        while (cur != null) {
            next = cur.next;
            cur.next = pre;
            pre = cur;
            cur = next;
        }
        return pre;
    }

    //合并两个有序链表
    private ListNode mergeLists(ListNode head1, ListNode head2) {
        if (head1 == null && head2 == null) {
            return null;
        }
        if (head1 == null || head2 == null) {
            return head1 == null ? head2 : head1;
        }
        ListNode first = new ListNode(-1);
        ListNode cur = first;
        while (head1 != null && head2 != null) {
            if (head1.val < head2.val) {
                cur.next = head1;
                head1 = head1.next;
            } else {
                cur.next = head2;
                head2 = head2.next;
            }
            cur = cur.next;
        }
        cur.next = head1 != null ? head1 : head2;
        return first.next;
    }

    //初始化链表
    private ListNode initList() {
        ListNode node1 = new ListNode(1);
        ListNode node2 = new ListNode(8);
        ListNode node3 = new ListNode(3);
        ListNode node4 = new ListNode(6);
        ListNode node5 = new ListNode(5);
        ListNode node6 = new ListNode(4);
        ListNode node7 = new ListNode(7);
        ListNode node8 = new ListNode(2);
        ListNode node9 = new ListNode(9);

        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
        node4.next = node5;
        node5.next = node6;
        node6.next = node7;
        node7.next = node8;
        node8.next = node9;
        return node1;
    }

    //打印链表
    private void printList(ListNode head) {
        if (head == null) {
            return;
        }
        ListNode cur = head;
        while (cur.next != null) {
            System.out.print(cur.val + "\t");
            cur = cur.next;
        }
        System.out.println(cur.val);
    }

32、全排列问题,DFS

//输入字符串abc,则打印出由字符a,b,c
//所能排列出来的所有字符串 abc,acb,bac,bca,cab 和 cba 。
    public ArrayList<String> Permutation(String str) {
        ArrayList<String> result = new ArrayList<>();
        if (str != null && str.length() > 0) {
            PermutationHelper(str.toCharArray(), 0, result);
            Collections.sort(result);
        }
        return result;
    }
    
    public void PermutationHelper(char[] str, int start, ArrayList<String> result) {
        if (start == str.length - 1) {
            if (!IsExist(result, str)) {
                result.add(new String(str));
            }
            return;
        }
        for (int i = start; i < str.length; i++) {
            Swap(str, start, i);
            PermutationHelper(str, start + 1, result);
            Swap(str, start, i);
        }
    }
    
    public void Swap(char[] str, int i, int j) {
        char temp = str[i];
        str[i] = str[j];
        str[j] = temp;
    }

    public boolean IsExist(ArrayList<String> result, char[] str) {
        return result.contains(String.valueOf(str));
    }

33、基于递归与回溯实现。全排列1,2,3

   //基于递归与回溯实现。全排列1,2,3的
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        List<Integer> temp = new ArrayList<>();
        for (int i : nums) {
            temp.add(i);
        }
        int len = nums.length;
        dfs(len, result, temp, 0);
        return result;
    }
    private void dfs(int len, List<List<Integer>> result, List<Integer> temp, int first) {
        if (first == len) {
            result.add(new ArrayList<>(temp));
        }
        for (int i = first; i < len; i++) {
            Collections.swap(temp,first,i);
            dfs(len,result,temp,first+1);
            Collections.swap(temp,first,i);
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值