首页 > 编程语言 >常用算法记录

常用算法记录

时间:2023-07-07 10:22:42浏览次数:40  
标签:index head right arr 记录 int 常用 算法 null

二叉树遍历

https://leetcode.cn/problems/binary-tree-preorder-traversal/solutions/87526/leetcodesuan-fa-xiu-lian-dong-hua-yan-shi-xbian-2/

递归解法

前序遍历

public static void preOrderRecur(TreeNode head) {
    if (head == null) {
        return;
    }
    System.out.print(head.value + " ");
    preOrderRecur(head.left);
    preOrderRecur(head.right);
}

作者:golandscape
链接:https://leetcode.cn/problems/binary-tree-preorder-traversal/solutions/87526/leetcodesuan-fa-xiu-lian-dong-hua-yan-shi-xbian-2/

  

中序遍历

public static void preOrderRecur(TreeNode head) {
    if (head == null) {
        return;
    }
    preOrderRecur(head.left);
    System.out.print(head.value + " ");
    preOrderRecur(head.right);
}

作者:golandscape
链接:https://leetcode.cn/problems/binary-tree-preorder-traversal/solutions/87526/leetcodesuan-fa-xiu-lian-dong-hua-yan-shi-xbian-2/

  

后序遍历

public static void postOrderRecur(TreeNode head) {
    if (head == null) {
        return;
    }
    postOrderRecur(head.left);
    postOrderRecur(head.right);
    System.out.print(head.value + " ");
}

作者:golandscape
链接:https://leetcode.cn/problems/binary-tree-preorder-traversal/solutions/87526/leetcodesuan-fa-xiu-lian-dong-hua-yan-shi-xbian-2/

  

迭代解法

本质上是在模拟递归,因为在递归的过程中使用了系统栈,所以在迭代的解法中常用 Stack 来模拟系统栈。

前序遍历

public static void preOrderIteration(TreeNode head) {
	if (head == null) {
		return;
	}
	Stack<TreeNode> stack = new Stack<>();
	stack.push(head);
	while (!stack.isEmpty()) {
		TreeNode node = stack.pop();
		System.out.print(node.value + " ");
		if (node.right != null) {
			stack.push(node.right);
		}
		if (node.left != null) {
			stack.push(node.left);
		}
	}
}

作者:golandscape
链接:https://leetcode.cn/problems/binary-tree-preorder-traversal/solutions/87526/leetcodesuan-fa-xiu-lian-dong-hua-yan-shi-xbian-2/

  

中序遍历

public static void inOrderIteration(TreeNode head) {
	if (head == null) {
		return;
	}
	TreeNode cur = head;
	Stack<TreeNode> stack = new Stack<>();
	while (!stack.isEmpty() || cur != null) {
		while (cur != null) {
			stack.push(cur);
			cur = cur.left;
		}
		TreeNode node = stack.pop();
		System.out.print(node.value + " ");
		if (node.right != null) {
			cur = node.right;
		}
	}
}

作者:golandscape
链接:https://leetcode.cn/problems/binary-tree-preorder-traversal/solutions/87526/leetcodesuan-fa-xiu-lian-dong-hua-yan-shi-xbian-2/

  

后顺遍历

public static void postOrderIteration(TreeNode head) {
		if (head == null) {
			return;
		}
		Stack<TreeNode> stack1 = new Stack<>();
		Stack<TreeNode> stack2 = new Stack<>();
		stack1.push(head);
		while (!stack1.isEmpty()) {
			TreeNode node = stack1.pop();
			stack2.push(node);
			if (node.left != null) {
				stack1.push(node.left);
			}
			if (node.right != null) {
				stack1.push(node.right);
			}
		}
		while (!stack2.isEmpty()) {
			System.out.print(stack2.pop().value + " ");
		}
	}

作者:golandscape
链接:https://leetcode.cn/problems/binary-tree-preorder-traversal/solutions/87526/leetcodesuan-fa-xiu-lian-dong-hua-yan-shi-xbian-2/

  

层序遍历

class Solution {
    public int maxDepth(TreeNode root) {
        if(root == null) return 0;
        List<TreeNode> queue = new LinkedList<>() {{ add(root); }}, tmp;
        int res = 0;
        while(!queue.isEmpty()) {
            tmp = new LinkedList<>();
            for(TreeNode node : queue) {
                if(node.left != null) tmp.add(node.left);
                if(node.right != null) tmp.add(node.right);
            }
            queue = tmp;
            res++;
        }
        return res;
    }
}

作者:Krahets
链接:https://leetcode.cn/problems/er-cha-shu-de-shen-du-lcof/solutions/159058/mian-shi-ti-55-i-er-cha-shu-de-shen-du-xian-xu-bia/

  

排序算法

https://leetcode.cn/circle/article/Gwd1Z5/

https://leetcode.cn/circle/discuss/eBo9UB/#%E9%80%89%E6%8B%A9%E6%8E%92%E5%BA%8F

选择排序

public int[] selectionSortDouble(int[] arr) {
    if (arr.length < 2) return arr;
    int n = arr.length;
    for (int i = 0; i < n - 1 - i; i++) { // 每轮确定两个数字,因此上界也会动态变化
        int minIdx = i, maxIdx = i;
        for (int j = i + 1; j < n - i; j++) {
            if (arr[j] < arr[minIdx]) minIdx = j;
            if(arr[j] > arr[maxIdx]) maxIdx = j;
        }
        if(minIdx == maxIdx) break; // 若本轮最大值等于最小值,说明未排序部分所有元素相等,无需再排序
        swap(arr, i, minIdx); 
        if(maxIdx == i) maxIdx = minIdx; // 在交换 i 和 minIdx 时,有可能出现 i 即 maxIdx 的情况,此时需要修改 maxIdx 为 minIdx
        swap(arr, n - 1 - i, maxIdx); 
    }
    return arr;
}

作者:yukiyama
链接:https://leetcode.cn/circle/discuss/eBo9UB/

  

简单插入排序

// 简单插入排序:内层用 for
public int[] insertionSortUseWhile(int[] arr) {
    if (arr.length < 2) return arr;
    for (int i = 1; i < arr.length; i++) {
        int target = arr[i], j = i - 1;
        for (; j >= 0; j--) {
            if(target < arr[j]) arr[j + 1] = arr[j];
            else break;
        }
        arr[j + 1] = target;
    }
    return arr;
}

作者:yukiyama
链接:https://leetcode.cn/circle/discuss/eBo9UB/

  

双轴快排

public int[] dualPivotQuickSort(int[] arr) {
    if (arr.length < 2) return arr;
    dualPivotQuickSort(arr, 0, arr.length - 1); // 后两个参数是下标值
    return arr;
}
/*
 *     区间1               区间2                         区间3
 * +------------------------------------------------------------+
 * |  < pivot1  | pivot1 <= && <= pivot2  |    ?    | > pivot2  |
 * +------------------------------------------------------------+
 *              ^                         ^         ^
 *              |                         |         |
 *            lower                     index      upper
 */
private void dualPivotQuickSort(int[] arr, int left, int right) {
    if(left < right) { // 排序对象是right大于left的区间(即大小大于等于2的区间)
        // 令左右两端元素中较小者居左,以left为初始pivot1,right为初始pivot2
        // 即arr[left]为选定的左轴值,arr[right]为选定的右轴值
        if(arr[left] > arr[right]) {
            swap(arr, left, right);
        }
        int index = left + 1; // 当前考察元素下标
        int lower = left + 1; // 用于推进到pivot1最终位置的动态下标,总有[left, lower)确定在区间1中
        int upper = right - 1; // 用于推进到pivot2最终位置的动态下标,总有(upper, right]确定在区间3中
        // [lower, index)确定在区间2中,[index, upper]为待考察区间。

        // upper以右(不含upper)的元素都是确定在区间3的元素,所以考察元素的右界是upper
        while(index <= upper) {
            // 若arr[index] < arr[left],即arr[index]小于左轴值,则arr[index]位于区间1
            if (arr[index] < arr[left]) {
                // 交换arr[index]和arr[lower],配合后一条lower++,保证arr[index]位于区间1
                swap(arr, index, lower); 
                // lower++,扩展区间1,lower位置向右一位靠近pivot1的最终位置
                lower++;
            }
            // 若arr[index] > arr[right],即arr[index]大于右轴值,则arr[index]位于区间3
            else if(arr[index] > arr[right]) {
                // 先扩展区间3,使得如下while结束后upper以右(不含upper)的元素都位于区间3
                // 区间3左扩不可使index == upper,否则之后的第二条upper--将导致upper为一个已经确定了区间归属的元素的位置(即index - 1)
                while(arr[upper] > arr[right] && index < upper) {
                    upper--;
                }
                // 交换arr[index]和arr[upper],配合后一条upper--,保证arr[index]位于区间3
                swap(arr, index, upper);
                upper--;
                // 上述交换后,index上的数字已经改变,只知道此时arr[index] ≤ arr[right],arr[index]有可能在区间1或区间2,
                // 若arr[index] < arr[left],即arr[index]小于左轴值,则arr[index]位于区间1
                if(arr[index] < arr[left]) {
                    // 交换arr[index]和arr[lower],配合后一条lower++,保证arr[index]位于区间1
                    swap(arr, index, lower);
                    // lower++,扩展区间1,lower位置向右一位靠近pivot1的最终位置
                    lower++;
                }
            }
            index++; // 考察下一个数字
        }
        // while(index <= upper)结束后最后一个确定在区间1的元素的下标是lower--,
        // 最后一个确定在区间3的元素下标是upper++。
        lower--;
        upper++;
        // 双轴归位。此时的lower,upper即分别为最终pivot1(初始时为left),最终pivot2(初始时为right)。
        swap(arr, left, lower);
        swap(arr, upper, right);
        // 对三个子区间分别执行双轴快排
        dualPivotQuickSort(arr, left, lower - 1); // 区间1
        dualPivotQuickSort(arr, lower + 1, upper - 1); // 区间2
        dualPivotQuickSort(arr, upper + 1, right); // 区间3
    }
}

作者:yukiyama
链接:https://leetcode.cn/circle/discuss/eBo9UB/

  

堆排序

https://www.cnblogs.com/jiangym/p/17521231.html

链表

反转链表

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode pre = null;
        ListNode cur = head;
        while(cur != null){
            ListNode tmp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = tmp;
        }
        
        return pre;
    }
}

环形链表

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode fast = head, slow = head;
        while (true) {
            if (fast == null || fast.next == null) return null;
            fast = fast.next.next;
            slow = slow.next;
            if (fast == slow) break;
        }
        fast = head;
        while (slow != fast) {
            slow = slow.next;
            fast = fast.next;
        }
        return fast;
    }
}

作者:Krahets
链接:https://leetcode.cn/problems/linked-list-cycle-ii/solutions/12616/linked-list-cycle-ii-kuai-man-zhi-zhen-shuang-zhi-/

给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

题解

设两指针 fastslow 指向链表头部 headfast 每轮走 2步,slow 每轮走 1步;

双指针第一次相遇:

第一种结果: fast 指针走过链表末端,说明链表无环,直接返回 null

第二种结果: 当fast == slow时, 两指针在环中 第一次相遇 。

  指针 位置不变 ,将fast指针重新 指向链表头部节点 ;slowfast同时每轮向前走 1 步;

返回slow指针指向的节点。

 

标签:index,head,right,arr,记录,int,常用,算法,null
From: https://www.cnblogs.com/jiangym/p/17534114.html

相关文章

  • 几个经典算法的概念
    动态规划(DynamicProgramming) 一、动态规划的基本思想:   动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一个解都对应于一个值,我们希望找到具有最优值的解。动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题......
  • Kotlin 常用语法糖记录
    原文地址:Kotlin常用语法糖记录-Stars-One的杂货小窝当使用Kotlin编程时,有一些常用的函数可以帮助我们简化代码并提高开发效率。稍微列举下常用的方法runCatchingrunCatching是一个用于处理可能引发异常的代码块的函数。它提供了一种更简洁和安全的方式来执行可能出现......
  • 数据结构(算法)【7月6日】
    一、算法的基本概念:1、算法是对特定问题求解步骤的一种描述,它是指令的有限序列,其中的每条指令表示一个或多个操作。2、算法的特性:(1)有穷性:一个算法必须总在执行有穷步之后结束,且每一步都可在有穷时间内完成;【算法是有穷的,程序是无穷的】(2)确定性:算法中每条指令必须有确切的含义,......
  • Linux中常用数据库管理系统之MariaDB
    我们生活在信息化时代,经常要跟数据打交道,它在我们的日常生活中无处不在,比如手机支付,微信聊天,淘宝购物,使用的这些在后台都会对应一个叫数据库的存在。数据库就是存储这些数据资料的仓库,那么这些数据是如何被管理的呢?今天我们就来一起了解下数据库管理系统。所谓数据库管理系统,就这......
  • Linux中常用数据库管理系统之MariaDB
    我们生活在信息化时代,经常要跟数据打交道,它在我们的日常生活中无处不在,比如手机支付,微信聊天,淘宝购物,使用的这些在后台都会对应一个叫数据库的存在。数据库就是存储这些数据资料的仓库,那么这些数据是如何被管理的呢?今天我们就来一起了解下数据库管理系统。所谓数据库管理系统,就这......
  • Linux中常用数据库管理系统之MariaDB
    我们生活在信息化时代,经常要跟数据打交道,它在我们的日常生活中无处不在,比如手机支付,微信聊天,淘宝购物,使用的这些在后台都会对应一个叫数据库的存在。数据库就是存储这些数据资料的仓库,那么这些数据是如何被管理的呢?今天我们就来一起了解下数据库管理系统。所谓数据库管理系统,就这......
  • Docker CLI docker container kill 常用命令
    Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实现虚拟化。Docker是内核虚拟化,不使用Hypervisor是不完全虚拟化,依赖内核的特性实现资源隔离。本文主要介绍DockerCLI中d......
  • SRGAN图像超分重建算法Python实现(含数据集代码)
    摘要:本文介绍深度学习的SRGAN图像超分重建算法,使用Python以及Pytorch框架实现,包含完整训练、测试代码,以及训练数据集文件。博文介绍图像超分算法的原理,包括生成对抗网络和SRGAN模型原理和实现的代码,同时结合具体内容进行解释说明,完整代码资源文件请转至文末的下载链接。完整......
  • vim 常用命令
    vim进入vimi:command->editesc:edit->command:wqa.cpp保存->退出(文件名:a.cpp):syntaxon:高亮:setnumber显示行号:q!不保存->退出vim~/.vimrc命令模式下:w跳过下一个单词h左j上k下l右b往回跳一个单词ctrl+f往下翻页ctrl+b往上翻页......
  • 数据结构与算法1-2
    王争,西安交通大学计算机专业本科毕业时候编程水平其实是很差的。读研究生看《算法导论》。从此我对算法的“迷恋”便一发不可收拾。之后,我如把图书馆里几乎所有数据结构和算法书籍都读了一遍。我边读边练。没多久我就发现,写代码时会不由自主考虑很多性能方面的问题。我写出时间......