Android學習總結之算法篇三(排序)

歸并排序原理

歸并排序(Merge Sort)是一種采用分治法(Divide and Conquer)的排序算法,其基本思想是將一個大問題分解為多個小問題,分別解決這些小問題,然后將小問題的解合并起來得到原問題的解。具體步驟如下:

  1. 分解(Divide):將待排序的數組從中間分成兩個子數組,遞歸地對這兩個子數組繼續進行分解,直到每個子數組中只有一個元素(因為單個元素的數組本身就是有序的)。

  2. 解決(Conquer):對每個子數組進行排序,由于每個子數組只有一個元素,所以這一步實際上已經完成了排序。

  3. 合并(Merge):將兩個已排序的子數組合并成一個新的有序數組。重復這個合并過程,直到所有的子數組合并成一個完整的有序數組。

代碼實現及注釋

下面是用 Java 實現的歸并排序代碼,并帶有詳細的注釋:

public class MergeSort {// 歸并排序的主函數public static void mergeSort(int[] arr) {if (arr == null || arr.length <= 1) {return; // 如果數組為空或只有一個元素,無需排序}int[] temp = new int[arr.length]; // 創建一個臨時數組,用于合并過程mergeSort(arr, 0, arr.length - 1, temp);}// 遞歸進行歸并排序private static void mergeSort(int[] arr, int left, int right, int[] temp) {if (left < right) {int mid = left + (right - left) / 2; // 計算中間位置// 遞歸排序左半部分mergeSort(arr, left, mid, temp);// 遞歸排序右半部分mergeSort(arr, mid + 1, right, temp);// 合并兩個已排序的子數組merge(arr, left, mid, right, temp);}}// 合并兩個已排序的子數組private static void merge(int[] arr, int left, int mid, int right, int[] temp) {int i = left; // 左子數組的起始索引int j = mid + 1; // 右子數組的起始索引int k = left; // 臨時數組的起始索引// 比較左右子數組的元素,將較小的元素放入臨時數組while (i <= mid && j <= right) {if (arr[i] <= arr[j]) {temp[k++] = arr[i++];} else {temp[k++] = arr[j++];}}// 將左子數組中剩余的元素復制到臨時數組while (i <= mid) {temp[k++] = arr[i++];}// 將右子數組中剩余的元素復制到臨時數組while (j <= right) {temp[k++] = arr[j++];}// 將臨時數組中的元素復制回原數組for (k = left; k <= right; k++) {arr[k] = temp[k];}}public static void main(String[] args) {int[] arr = {9, 5, 7, 1, 3, 8, 4, 2, 6};mergeSort(arr);for (int num : arr) {System.out.print(num + " ");}}
}

?

100000個數字中,對前10000小的數字進行排序(堆排)

import java.util.Arrays;
import java.util.PriorityQueue;public class SortTop10000Smallest {/*** 從給定的數字數組中找出前 10000 小的數字** @param numbers 包含 100000 個數字的數組* @return 包含前 10000 小數字的數組*/public static int[] getTop10000Smallest(int[] numbers) {// 創建一個最大堆,堆的大小為 10000。// 通過自定義比較器 (a, b) -> b - a 來實現最大堆,即堆頂元素為堆中最大的元素PriorityQueue<Integer> maxHeap = new PriorityQueue<>(10000, (a, b) -> b - a);// 遍歷給定的數字數組for (int num : numbers) {if (maxHeap.size() < 10000) {// 如果堆的大小小于 10000,直接將當前數字加入堆中maxHeap.offer(num);} else if (num < maxHeap.peek()) {// 如果堆的大小已經達到 10000,且當前數字小于堆頂元素// 則移除堆頂元素(即當前堆中的最大元素),并將當前數字加入堆中maxHeap.poll();maxHeap.offer(num);}}// 創建一個大小為 10000 的數組,用于存儲最終的前 10000 小的數字int[] top10000 = new int[10000];// 從數組的最后一個位置開始,將堆中的元素依次取出放入數組中for (int i = 9999; i >= 0; i--) {top10000[i] = maxHeap.poll();}return top10000;}public static void main(String[] args) {// 生成一個包含 100000 個隨機數字的數組,數字范圍在 0 到 999999 之間int[] numbers = new int[100000];for (int i = 0; i < 100000; i++) {numbers[i] = (int) (Math.random() * 1000000);}// 調用 getTop10000Smallest 方法,獲取前 10000 小的數字int[] top10000 = getTop10000Smallest(numbers);// 對前 10000 小的數字進行排序,使用 Arrays 類的 sort 方法Arrays.sort(top10000);// 遍歷排序后的數組,打印每個數字for (int num : top10000) {System.out.println(num);}}
}    

代碼解釋

  1. 最大堆的創建:使用?PriorityQueue?來創建一個最大堆,堆的大小為 10000。通過自定義比較器?(a, b) -> b - a?來實現最大堆。
  2. 遍歷數字數組:遍歷 100000 個數字,若堆的大小小于 10000,直接將數字加入堆中;若當前數字小于堆頂元素,移除堆頂元素并加入當前數字。
  3. 將堆中的元素轉換為數組:遍歷堆,將堆中的元素依次取出放入數組中。
  4. 對前 10000 小的數字進行排序:使用?Arrays.sort?方法對數組進行排序。
  5. 打印排序后的結果:遍歷排序后的數組,打印每個元素。

?

?二叉樹中最近公共祖先(LCA)

二叉樹節點定義

class TreeNode {int val;TreeNode left;TreeNode right;TreeNode(int x) { val = x; }
}

最近公共祖先算法(遞歸解法)

public class LowestCommonAncestor {// 主函數:查找 p 和 q 的最近公共祖先public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {// 遞歸終止條件:當前節點為空,或找到 p 或 q(自己也是自己的祖先)if (root == null || root == p || root == q) {return root;}// 遞歸查找左子樹和右子樹TreeNode left = lowestCommonAncestor(root.left, p, q);TreeNode right = lowestCommonAncestor(root.right, p, q);// 情況 1:左子樹和右子樹都找到節點 → 說明當前根節點是 LCAif (left != null && right != null) {return root;}// 情況 2:左子樹找到節點,右子樹沒找到 → 返回左子樹的結果(可能是 p/q 或它們的祖先)else if (left != null) {return left;}// 情況 3:右子樹找到節點,左子樹沒找到 → 返回右子樹的結果else {return right;}}// 測試用例public static void main(String[] args) {// 構建示例二叉樹TreeNode root = new TreeNode(3);root.left = new TreeNode(5);root.right = new TreeNode(1);root.left.left = new TreeNode(6);root.left.right = new TreeNode(2);root.right.left = new TreeNode(0);root.right.right = new TreeNode(8);root.left.right.left = new TreeNode(7);root.left.right.right = new TreeNode(4);LowestCommonAncestor solution = new LowestCommonAncestor();// 測試案例 1:p=5, q=1 → LCA 是 root(3)TreeNode p = root.left; // val=5TreeNode q = root.right; // val=1System.out.println("LCA of 5 and 1 is: " + solution.lowestCommonAncestor(root, p, q).val); // 輸出 3// 測試案例 2:p=5, q=4 → LCA 是 5q = root.left.right.right; // val=4System.out.println("LCA of 5 and 4 is: " + solution.lowestCommonAncestor(root, p, q).val); // 輸出 5// 測試案例 3:p=7, q=4 → LCA 是 2TreeNode p2 = root.left.right.left; // val=7q = root.left.right.right; // val=4System.out.println("LCA of 7 and 4 is: " + solution.lowestCommonAncestor(root, p2, q).val); // 輸出 2}
}

算法原理(遞歸三要素)

  1. 終止條件

    • 當前節點為空(root == null):說明沒找到,返回?null
    • 當前節點是?p?或?q:直接返回自己(自己是自己的祖先)
  2. 遞歸邏輯

    • 分別在左子樹和右子樹中查找?p?和?q?的祖先
    • 若左子樹和右子樹都找到節點 → 說明當前節點是它們的公共祖先(因為左子樹和右子樹各有一個節點,當前節點是最近的公共祖先)
    • 若只有左子樹找到 → 結果在左子樹中(可能是?p/q?或它們的祖先)
    • 若只有右子樹找到 → 結果在右子樹中
  3. 合并結果
    通過遞歸的返回值,自底向上判斷當前節點是否為 LCA,最終返回最近的那個祖先。

算法特點

  • 時間復雜度:O (n),每個節點最多被訪問一次
  • 空間復雜度:O (n)(遞歸棧空間,最壞情況下樹退化為鏈表)
  • 適用場景:二叉樹(無論是否為二叉搜索樹),且節點值唯一,p 和 q 一定存在于樹中

關鍵思路

  • 分治思想:將問題分解為左子樹和右子樹的子問題,通過子問題的解合并得到原問題的解
  • 后序遍歷:先處理左右子樹,再處理當前節點,符合 “自底向上” 查找祖先的邏輯
  • 唯一性假設:利用 “樹中節點值唯一” 的特性,直接通過節點引用判斷是否為 p 或 q

找View樹的最近公共祖先?

// 定義 View 類
class View {View[] childs;View parent;public View() {this.childs = null;this.parent = null;}
}public class ViewTreeLCA {// 查找兩個 View 的最近公共祖先public static View findLowestCommonAncestor(View view1, View view2) {// 存儲 view1 到根節點的路徑java.util.HashSet<View> path = new java.util.HashSet<>();// 從 view1 開始,將其到根節點的路徑上的所有 View 加入到 path 集合中View current = view1;while (current != null) {path.add(current);current = current.parent;}// 從 view2 開始,沿著其父節點向上遍歷current = view2;while (current != null) {// 如果當前 View 已經在 path 集合中,說明找到了最近公共祖先if (path.contains(current)) {return current;}current = current.parent;}// 如果沒有找到公共祖先,返回 nullreturn null;}public static void main(String[] args) {// 構建一個簡單的 View 樹View root = new View();View child1 = new View();View child2 = new View();View grandChild1 = new View();View grandChild2 = new View();root.childs = new View[]{child1, child2};child1.parent = root;child2.parent = root;child1.childs = new View[]{grandChild1};grandChild1.parent = child1;child2.childs = new View[]{grandChild2};grandChild2.parent = child2;// 查找 grandChild1 和 grandChild2 的最近公共祖先View lca = findLowestCommonAncestor(grandChild1, grandChild2);if (lca != null) {System.out.println("最近公共祖先是存在的。");} else {System.out.println("未找到最近公共祖先。");}}
}    

代碼思路:

  1. 存儲路徑:首先,從?view1?開始,沿著其父節點向上遍歷,將經過的所有?View?存儲在一個?HashSet?中,這個集合記錄了?view1?到根節點的路徑。
  2. 查找公共祖先:接著,從?view2?開始,同樣沿著其父節點向上遍歷。對于每個經過的?View,檢查它是否已經在之前存儲的路徑集合中。如果存在,說明找到了最近公共祖先,返回該?View
  3. 未找到情況:如果遍歷完?view2?到根節點的路徑都沒有找到公共祖先,返回?null

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/76682.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/76682.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/76682.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Python列表(List)深度解析

列表(List)是Python中最基礎且強大的數據結構之一&#xff0c;但它的底層實現和特性遠比表面看起來復雜。本文將深入探討列表的各個方面。 1. 列表基礎特性 1.1 可變序列類型 lst [1, 2, 3] lst[1] 20 # 可變性1.2 異構容器 mixed [1, "hello", 3.14, [1, 2]…

Java基礎-設計模式詳解

摘要&#xff1a;設計模式是軟件工程中解決常見問題的經典方案。本文結合Java語言特性&#xff0c;深入解析常用設計模式的核心思想、實現方式及實際應用場景&#xff0c;幫助開發者提升代碼質量和可維護性。 一、設計模式概述 1.1 什么是設計模式&#xff1f; 設計模式&…

Docker 構建鏡像異常報錯解決

報錯一&#xff1a; # 啟動 SSH Agent eval $(ssh-agent -s)# 添加私鑰到 agent (替換為你的實際密鑰路徑) ssh-add ~/.ssh/id_ed25519# 驗證密鑰已加載 ssh-add -L# 查看 SSH_AUTH_SOCK 是否設置 echo $SSH_AUTH_SOCK # 應輸出類似&#xff1a;/tmp/ssh-XXXXXX/agent.XXXX# 顯…

動態規劃似包非包系列一>組合總和IIV

目錄 題目分析&#xff1a;狀態表示&#xff1a;狀態轉移方程&#xff1a;初始化填表順序返回值&#xff1a;代碼呈現&#xff1a; 題目分析&#xff1a; 狀態表示&#xff1a; 狀態轉移方程&#xff1a; 初始化填表順序返回值&#xff1a; 代碼呈現&#xff1a; class Soluti…

Linux下調試器gdb_cgdb使用

文章目錄 一、樣例代碼二、使用watchset var確定問題原因條件斷點 一、樣例代碼 #include <stdio.h>int Sum(int s, int e) {int result 0;int i;for(i s; i < e; i){result i;}return result; }int main() {int start 1;int end 100;printf("I will begin…

JSON Crack:簡化數據可視化的參數編輯器

簡介 在當今數據驅動的世界中&#xff0c;JSON&#xff08;JavaScript Object Notation&#xff09;作為一種輕量級的數據交換格式&#xff0c;廣泛應用于各種開發和數據分析場景。然而&#xff0c;復雜的JSON數據往往難以閱讀和理解&#xff0c;特別是在數據量龐大時&#xf…

PostgreSQL 刪除數據庫

PostgreSQL 刪除數據庫 概述 PostgreSQL 是一款功能強大的開源關系型數據庫管理系統&#xff0c;它提供了豐富的功能和強大的性能。在數據庫管理過程中&#xff0c;有時需要刪除不再需要的數據庫&#xff0c;以釋放資源或進行數據庫維護。本文將詳細介紹如何在 PostgreSQL 中…

Linux內核物理內存組織結構

一、系統調用sys_mmap 系統調用mmap用來創建內存映射&#xff0c;把創建內存映射主要的工作委托給do_mmap函數&#xff0c;內核源碼文件處理&#xff1a;mm/mmap.c 二、系統調用sys_munmap 1、vma find_vma (mm, start); // 根據起始地址找到要刪除的第一個虛擬內存區域 vma 2…

Mac強制解鎖APP或文件夾

當Mac安裝過火絨企業版、云安全訪問服務之類的APP需要卸載的時候&#xff0c;會發現需要管理員密碼&#xff0c;正常的卸載流程走不下去&#xff0c;直接刪除APP&#xff0c;會提示“不能完成此操作&#xff0c;xxx已鎖定”的信息&#xff0c;此處就記錄一下如何關閉鎖定狀態&a…

Mixed Content: The page at https://xxx was loaded over HTTPS

一、核心原因分析 Mixed Content 警告是由于 HTTPS 頁面中引用了 HTTP 協議的資源(如腳本、圖片、iframe 等),導致瀏覽器因安全策略阻止加載這些非加密內容。HTTP 資源可能被中間人攻擊篡改,破壞 HTTPS 頁面的整體安全性。 二、推薦解決方案 1. 強制資源升級為 HTTPS ?…

ARXML文件解析-1

目錄 1 摘要2 ARXML文件2.1 作用及典型應用場景2.2 **ARXML文件的結構樹**2.3 TAG&#xff08;XML元素&#xff09;2.4 ARXML文件關鍵元素解析2.4.1 XML聲明與處理指令2.4.2 XML注釋2.4.3 ADMIN-DATA元素2.4.3 語言相關元素2.4.5 AR-PACKAGE體系結構2.4.6. 數據轉換框架2.4.7 S…

[ISP 3A ] AE的常用算法分析

&#x1f4cc; 自動曝光&#xff08;AE, Auto Exposure&#xff09;解析 自動曝光&#xff08;AE&#xff09;是相機通過調節 曝光參數&#xff08;增益、快門時間、光圈等&#xff09;來確保拍攝出的圖像亮度適宜的算法。AE 需要根據環境光線變化自動調整曝光&#xff0c;以避…

大模型學習二:DeepSeek R1+蒸餾模型組本地部署與調用

一、說明 DeepSeek R1蒸餾模型組是基于DeepSeek-R1模型體系&#xff0c;通過知識蒸餾技術優化形成的系列模型&#xff0c;旨在平衡性能與效率。 1、技術路徑與核心能力 基礎架構與訓練方法? ?DeepSeek-R1-Zero?&#xff1a;通過強化學習&#xff08;RL&#xff09;訓練&…

STM32入門學習筆記(持續更新)

b站江協科技資料 通過網盤分享的文件&#xff1a;STM32入門教程資料 鏈接: https://pan.baidu.com/s/1-rOi83sUK8CqUNsHQuvxew?pwd8krh 提取碼: 8krh LED燈閃爍0402 #include "stm32f10x.h" // Device header #include "Delay.h"int m…

企業安全——FIPs

0x00 前言 先來看一道題目。這道題目涉及到的就是道德規范和互聯網相關內容&#xff0c;本文會對相關內容進行描述和整理。 正確答案是&#xff1a;D 注意FIPs的主要目的是為了限制&#xff0c;也就是針對數據的守則。 0x01 RFC 1087 1989年1月 互聯網架構委員會 IAB 發布了…

【Linux系統編程】進程概念,進程狀態

目錄 一&#xff0c;操作系統&#xff08;Operator System&#xff09; 1-1概念 1-2設計操作系統的目的 1-3核心功能 1-4系統調用和庫函數概念 二&#xff0c;進程&#xff08;Process&#xff09; 2-1進程概念與基本操作 2-2task_struct結構體內容 2-3查看進程 2-4通…

基于TradingView和CTPBee的自動化期貨交易系統實現

引言 在量化交易領域&#xff0c;TradingView因其強大的技術分析工具和豐富的指標庫而廣受歡迎&#xff0c;但是其不支持國內期貨自動化交易&#xff0c;CTPBee則是一個優秀的國產Python期貨交易接口。本文將介紹如何將兩者結合&#xff0c;實現一個完整的自動化交易系統。 本…

初始ARM

ARM最基礎的組成單元。 最小系統&#xff1a;能系統能夠正常工作的最少器件構成的系統 。 一、CPU基礎定義 ALU&#xff08;運算單元&#xff09;&#xff1a; 負責執行算術和邏輯運算&#xff0c;是處理器的核心部分。 寄存器&#xff08;R0, R1, R12&#xff09;&#xff…

通信數據記錄儀-產品概念ID

總結: 1、支持高速CAN、支持容錯CAN、支持單線CAN(理解是支持不同的協議,CANFD、CAN2.0和LIN?) 2、 通過上位機設計時間

Qt QTableView QAbstractTableModel實現復選框+代理實現單元格編輯

話不多說&#xff0c;直接看代碼 一、Model 1、QTableModel_Test.h #pragma once#include <QAbstractTableModel> #include <QObject> #include <QModelIndex>class QTableModel_Test : public QAbstractTableModel {Q_OBJECT public:QTableModel_Test(Q…