本文共 8127 字,大约阅读时间需要 27 分钟。
算法,是计算机处理信息的重要方法。它是一种解决问题的思想和步骤,体现在计算机程序的设计与实现中。以下将从多个核心领域详细阐述常见算法及其实现思路。
排序是数据处理的基础,各种排序方法各有优劣。以下是三种常见排序方法的实现逻辑:
冒泡排序:每次通过比较相邻元素,完成一次交换,慢速排序。
public static int[] BubbleSort(int[] arr) { for (int i = 0; i < arr.length; i++) { for (int j = 0; j < arr.length - i - 1; j++) { if (arr[j] > arr[j + 1]) { int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } return arr;}
选择排序:通过最小值逐步建立有序数组。
public static int[] SelectSort(int[] arr) { for (int i = 0; i < arr.length - 1; i++) { for (int j = i + 1; j < arr.length; j++) { int temp = arr[i]; if (arr[i] > arr[j]) { arr[i] = arr[j]; arr[j] = temp; } } } return arr;}
快速排序:以交换栈的中位数为枢轴,递归划分数据集。
public int[] MySort(int[] arr) { quicksort(arr, 0, arr.length - 1); return arr;}public void quicksort(int[] list, int left, int right) { if (left < right) { int pivot = randompivot(list, left, right); quicksort(list, left, pivot - 1); quicksort(list, pivot + 1, right); }}public int randompivot(int[] list, int left, int right) { int first = list[left]; while (left < right) { while (left < right && list[right] >= first) { right--; } swap(list, left, right); while (left < right) { if (list[right] >= list[right - 1]) { right--; } else { break; } } } return left;}
通过模拟priority queue实现排序。堆排序的核心方法在于不断叠代地提取最大元素,最终形成有序数组。
堆排序通过模拟优先队列的性质,逐步构建有序数组。其时间复杂度为O(n log n),适用于大数据量的排序场景。
堆排序的实现思路是将数据按不规则插入,并通过上浮、下沉等操作维护堆的结构,最终提取有序信息。
在继续详细探讨其余算法前,记住排序算法及其复杂度对于后续学习至关重要。接下来将深入探讨数组操作、链表结构以及二叉树遍历等问题。
栈与队列是基础数据结构,具有先进先出和先进后出的特点之一。用栈实现队列是常见的练习。
通过“倒置栈”结构来模拟队列的先进先出特性。
public class Solution { Stack stack1 = new Stack(); Stack stack2 = new Stack(); public void push(int node) { stack1.push(node); } public int pop() { if (stack2.isEmpty()) { while (!stack1.isEmpty()) { stack2.push(stack1.pop()); } } return stack2.pop(); }}
通过线性时间算法解决字符串问题后,让人惊叹技术之美。
用队列作为缓存,逐个字符处理,避免重复。
public int maxLength(int[] arr) { Queue queue = new LinkedList(); int res = 0; for (int c : arr) { while (queue.contains(c)) { queue.poll(); } queue.add(c); res = Math.max(res, queue.size()); } return res;}
数组操作涉及数学建模,比如斐波那契数列和两数之和问题。
递归与非递归方法各有优劣,选择适合的实现则需要根据具体需求。
public int Fibonacci(int n) { if (n <= 1) return n; return Fibonacci(n - 1) + Fibonacci(n - 2);}
非递归实现:
public int Fibonacci(int n) { if (n <= 1) return n; int first = 0, second = 1, temp; for (int i = 2; i <= n; i++) { temp = second; second = first + second; first = temp; } return second;}
利用哈希表快速查找,时间复杂度为O(n)。
public int[] twoSum(int[] numbers, int target) { Map map = new HashMap(); for (int index = 0; index < numbers.length; index++) { int cur = numbers[index]; if (map.containsKey(target - cur)) { return new int[]{map.get(target - cur) + 1, index + 1}; } map.put(cur, index); } throw new RuntimeException("results not exits");}
链表常用于随机访问和多个结点操作,这些问题的解决往往别具匠心。
逐个结点逆向连接。
public ListNode ReverseList(ListNode head) { ListNode pre = null; ListNode cur = head; while (cur != null) { pre = cur.next; cur.next = pre; cur = pre; } return pre;}
利用双指针速度差异检测环的存在。
public class Solution { public boolean hasCycle(ListNode head) { if (head == null) return false; ListNode fast = head; ListNode slow = head; while (fast != null && fast.next != null) { slow = slow.next; fast = fast.next.next; if (fast == slow) return true; } return false; }}
分割链表后逐步追击。
public ListNode FindKthToTail(ListNode pHead, int k) { if (pHead == null) return pHead; ListNode first = pHead; while (k-- > 0) { if (first == null) return null; first = first.next; } ListNode second = pHead; while (first != null) { first = first.next; second = second.next; } return second;}
按大小顺序添加。递归法:
public ListNode mergeTwoLists(ListNode l1, ListNode l2) { if (l1 == null || l2 == null) { return l1 == null ? l2 : l1; } if (l1.val < l2.val) { l1.next = mergeTwoLists(l1.next, l2); return l1; } else { l2.next = mergeTwoLists(l1, l2.next); return l2; }}
非递归法:
public class Solution { public ListNode mergeTwoLists(ListNode l1, ListNode l2) { if (l1 == null) return l2; if (l2 == null) return l1; ListNode dummy = new ListNode(0); ListNode cur = dummy; while (l1 != null && l2 != null) { if (l1.val > l2.val) { cur.next = l2; l2 = l2.next; } else { cur.next = l1; l1 = l1.next; } cur = cur.next; } cur.next = l1 == null ? l2 : l1; return dummy.next; }}
利用双指针法追踪两链表的交点。
public class Solution { public ListNode detectCycle(ListNode head) { if (head == null || head.next == null) return null; ListNode fast = head; ListNode slow = head; while (fast != null && fast.next != null) { slow = slow.next; fast = fast.next.next; if (fast == slow) { fast = head; while (fast != slow) { slow = slow.next; fast = fast.next; } return slow; } } return null; }}
关于二叉树,关键问题包括树的完整性、树的高度、层序遍历以及树的翻转操作等。
通过遍历验证叶节点特性。
public boolean isFull(TreeNode root) { if (root == null) return false; Queue queue = new LinkedList(); boolean isLeaf = false; while (!queue.isEmpty()) { TreeNode node = queue.poll(); if (isLeaf && !isLeaf(node)) { return false; } if (node.left != null) { queue.offer(node); if (node.right != null) { return false; } } else if (node.right != null) { return false; } else { isLeaf = true; } } return true;}
递归或迭代求解树的最大高度。
public int maxDepth(TreeNode root) { if (root == null) return 0; return 1 + Math.max(maxDepth(root.left), maxDepth(root.right));}
将树按层遍历,记录递进依据。
public ArrayList levelOrder(TreeNode root) { if (root == null) return new ArrayList(); ArrayList list = new ArrayList(); Queue queue = new LinkedList(); queue.offer(root); while (!queue.isEmpty()) { int size = queue.size(); ArrayList subList = new ArrayList(); for (int i = 0; i < size; i++) { TreeNode node = queue.poll(); subList.add(node.val); if (node.left != null) queue.offer(node.left); if (node.right != null) queue.offer(node.right); } list.add(subList); } return list;}
结合层数交替,形成cross_walk。
public ArrayList zigzagLevelOrder(TreeNode root) { if (root == null) return new ArrayList(); ArrayList list = new ArrayList(); Queue queue = new LinkedList(); queue.offer(root); while (!queue.isEmpty()) { ArrayList subList = new ArrayList(); for (int i = queue.size(); i > 0; i--) { TreeNode node = queue.poll(); if ((list.size() + 1) % 2 != 0) { subList.add(node.val); } else { subList.add(0, node.val); } if (node.left != null) queue.offer(node.left); if (node.right != null) queue.offer(node.right); } list.add(subList); } return list;}
通过递归交换左右子节点。
public TreeNode invertTree(TreeNode node) { if (node == null) return null; TreeNode temp = node.left; node.left = node.right; node.right = temp; invertTree(node.left); invertTree(node.right); return node;}
通过以上细节,总结技术人员解题思路和方法,这些内容涵盖了算法与数据结构的基础,希望能为你的学习提供有价值的参考。
转载地址:http://fljuk.baihongyu.com/