LeetCode集

news2024/11/18 15:36:18

目录

  • 1、算法
    • 1.1 排序
      • 1.1.1 冒泡排序
        • 1.1.1.1 简单交换排序
        • 1.1.1.2 冒泡排序
      • 1.1.2 简单选择排序
      • 1.1.3 直接插入排序
      • 1.1.4 希尔排序
      • 1.1.5 堆排序
      • 1.1.6 归并排序
      • 1.1.7 快速排序
    • 1.1 位运算/二进制
      • 1.1.1 Java中的正数、负数
      • 1.1.2 Java中的位运算
      • 1.1.3 比特位计数
      • 1.1.4 2的幂
      • 1.1.5 3的幂
      • 1.1.6 LeetCode中的题目
  • 2、数据结构
    • 2.1 链表
    • 2.2 Deque
      • 2.2.1 Deque实现队列
      • 2.2.2 Deque实现堆栈
  • 3、数学
  • 3.1 快乐数
    • 3.2 丑数
  • 4、Tips
    • 4.1 超出时间限制
    • 4.2 简化String的计算量

1、算法

1.1 排序

排序算法主要有以下7类:冒泡排序、简单选择排序、直接插入排序、希尔排序、堆排序、归并排序、快速排序。其各自的性能表现如下:

排序方法平均情况最好情况最坏情况辅助空间稳定性
冒泡排序O(n2)O(n)O(n2)O(1)稳定
简单选择排序O(n2)O(n2)O(n2)O(1)稳定
直接插入排序O(n2)O(n)O(n2)O(1)稳定
希尔排序O(nlogn)~O(n2)O(n1.3)O(n2)O(1)不稳定
堆排序O(nlogn)O(nlogn)O(nlogn)O(1)不稳定
归并排序O(nlogn)O(nlogn)O(nlogn)O(n)稳定
快速排序O(nlogn)O(nlogn)O(n2)O(logn)~O(n)不稳定

接下来分别给出每个排序算法的核心示例伪代码。

void swap(int i, int j) {
	int temp = i;
	i = j;
	j = temp;
}

1.1.1 冒泡排序

1.1.1.1 简单交换排序

void bubbleSort1(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]) {
				swap(nums[i], nums[j]);
			}
		}
	}
}

这个排序严格意义上来说,应该只是简单交换排序,不能算是冒泡排序,因为它不满足“两两比较相邻记录”的冒泡排序思想。

1.1.1.2 冒泡排序

void bubbleSort2(int[] nums) {
	for (int i = 0; i < nums.length - 1; i++) {
		for (int j = nums.length - 1; j >= i; j--){
			if (nums[j] > nums [j+1]) {//若前一个数字大于后一个数字则交换
				swap(nums[j] > nums[j+1]);
			}
		}
	}
}

在这个排序中,小的数字如同气泡一般慢慢浮到上面,因此才是冒泡算法。

1.1.2 简单选择排序

简单选择排序的基本思想是每一趟再n-i+1(i=1,2,…,n-1)个记录中选取关键字最小的记录作为有序序列的第i个记录。

void selectSort(int[] nums) {
	int min;
	for (int i = 0; i < nums.length - 1; i++) {
		min = i;
		for (int j = i + 1; j < nums.length; j++) {
			if (nums[min] > nums[j]) {
				min = j;
			}
		}
		if (i != min) {
			swap(i, min);
		}
	}
}

1.1.3 直接插入排序

直接插入排序和打扑克牌一边摸牌一边理牌的过程相似,即不断将未排序的数插入到已经排好序的有序表中。

void insertSort(int[] nums) {
	//将数组的第一个元素当作已经排序好的有序表,从第二个元素开始排序
	for (int i = 1, j, current;i < nums.length; i++) {
		//从外循环开始,把当前i指向的值用current保存
		current = nums[i];
		//内循环,和current值比较;若j所指向的值比current大,则该数向后移一位
		for (int j = i - 1; j >= 0 && nums[j] > current; j--) {
			nums[j+1] = nums[j];
		}
		//内循环结束,j+1所指向的位置就是current值插入的位置
		nums[j+1] = current;
	}
}

1.1.4 希尔排序

在希尔排序之前,排序算法的时间复杂度基本都是O(n2),希尔排序是突破这个时间复杂度的第一批算法之一。希尔排序的基本思想是将数组分成若干个小组,对小组内的数字进行排序得到一个基本有序的若干个小组,然后将这些基本有序的若干个小组合并成较大的小组,对较大的小组组内排序。如此往复,得到最终结果。

void shellSort(int[] nums, int n) {
	int i, j, temp;
	int step;//步长增量

	for (step = n/2; step > 0;step /=2) {
		for (int i = step; i < n; i++) {
			temp = nums[i];
			j = i - step;
			for (; j >= 0 && temp < nums[j]; ) {]
				nums[j + step] = nums[j];
				j -= step;
			}
			nums[j + step] = temp;
		}
	}
}

1.1.5 堆排序

先给出大顶堆小顶堆的定义。堆是具有如下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。
堆排序采用大顶堆进行排序。将待排序的序列构造成大顶堆,此时,序列的根结点就是序列的最大值。将它与序列末尾的数字交换然后移走,得到最大值;剩余n-1个数字继续按大顶堆构造并重复之前的步骤。如此反复,得到最终的有序序列。
在这里插入图片描述

void heapSort(int[] nums) {
	int i;
	for (i = nums.length/2; i > 0; i--) {
		heapAdjust(nums, i, nums.length);
	}
	for (i = nums.length; i > 1; i--) {
		swap(nums, 1, i);
		heapAdjust(nums, 1, i - 1); 
	}
}
/**
*将array[s..m]调整成一个大顶堆
*/
void heapAdjust(int[] array, int s, int m) {
	int temp, j;
	temp = array[s];
	for(j = 2 * s; j <= m; j *= 2 ) {//沿关键字较大的子结点向下筛选
		if (j < m && array[j] < array[j + 1]) {
			++j; //j为关键字中较大的记录的下标
		}
		if (temp >= array[j])
			break;
		nums[s] = nums[j];
	}
	nums[s] = temp; //插入
}

1.1.6 归并排序

归并排序采用分治的思想,分为自顶向下或自底向上分治。归并排序的步骤可以用下图表示:
归并排序

void mergeSort(int[] nums, int first, int last, int[] temp) {
	if (first < last) {
		int mid = (first + last)/2;
		mergeSort(nums, first, mid, temp);
		mergeSort(nums, mid + 1, last, temp);
		mergeArray(nums, first, mid, last, temp);//合并两个有序数组
	}
}

void mergeArray(int[] array, int first, int mid, int last, int[] temp) {
	int i = first, j = mid + 1;
	int m = mid, n = last;
	int k = 0;
	while (i <= m && j <= n) {
		if (array[i] <= array[j]) {
			temp[k++] = array[i++];
		} else {
			temp[k++] = array[j++];
		}
		//如果比较完毕,第一组还有剩下,全部填入temp
		while (i <= m) {
			temp[k++] = array[i++];
		}
		//如果比较完毕,第二组还有剩下,全部填入temp
		while (j <= n) {
			temp[k++] = array[j++];
		}
		for (i = 0; i < k; i++) {
			array[first + i] = temp[i];
		}
	}
}

1.1.7 快速排序

采用分治的思想,比基准小的放在左边,比基准大的放在右边。最坏情况退化为冒泡排序。

void quickSort(int[] nums, int left, int right) {
	if (left < right) {
		int partitionIndex = partition(nums, left, right);
		quickSort(nums, left, partitionIndex - 1);
		quickSort(nums, partitionIndex + 1, right);
	}
}

int partition(int[] array, int left, int right) {
	//设置基准值pivot
	int pivot = left;
	int index = pivot + 1;
	for (int i = index; i <= right; i++) {
		if (array[i] < array[pivot]) {
			swap(array, i, index);
			index++;
		}
	}
	swap(array, pivot, index - 1);
}

1.1 位运算/二进制

1.1.1 Java中的正数、负数

Java中,编译器使用二进制补码来表示有符号整数。在Java里,正数的原码、反码、补码都是它本身。重点说一下Java中负数的原码、反码、补码。

  • 负数的原码:最高位表示符号, 其余位表示值
    [-1]原 = 1000 0001原
  • 负数的反码:符号位不变,其余各个位取反
    [-1] = [1000 0001]原 = [1111 1110]反
  • 负数的补码:在反码的基础上+1
    [-1] = [1000 0001]原 = [1111 1110]反 = [1111 1111]补
  • 求负数的原码:
    符号位不变,补码减1再取反
    符号位不变,补码取反再加1

1.1.2 Java中的位运算

  • 左移运算时,要特别考虑数据是否溢出。
  • >>> :表示无符号右移运算(逻辑右移),将一个数表示的二进制无符号向右移n位,移出的部分将被抛弃,无论是正数,还是负数,左侧高位都补0

1.1.3 比特位计数

Brian Kernighan’s 算法是一种用于计算一个整数的二进制表示中有多少个1的高效算法。该算法的基本思想是对于任意整数 x,令 x=x & (x−1),每次将该整数的最右边的一个1置为0,直到该整数变为0为止。每次将1置为0的操作都会使得该整数的二进制表示中的1的个数减少1。示意图如下:
在这里插入图片描述

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

1.1.4 2的幂

重要结论:如果一个数n是2的幂,当且仅当n是正整数时,n的二进制表示中仅包含1个1。用二进制表示如下:

0b1
0b10
0b100
0b1000
0b10000
0b100000
0b1000000
……

有以下推论:

  • n&(n-1)=0
  • n&(-n)=n

1.1.5 3的幂

可以采用试除法,不断地将n除以3,知道n=1。如果在此过程中n无法被3整除,就说明n不是3的幂。

1.1.6 LeetCode中的题目

190:颠倒二进制位
191:位1的个数
231:2的幂
326:3的幂
338:比特位计数

2、数据结构

2.1 链表

1、链表通常需要进行遍历,所以可以创建哑节点指向头结点。
2、链表通常可以使用递归求解,不过递归较难理解。

2.2 Deque

2.2.1 Deque实现队列

Deque<Integer> queue=new ArrayDeque<>();

2.2.2 Deque实现堆栈

Deque<Integer> stack=new LinkedList<>();

3、数学

3.1 快乐数

定义:

  • 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
  • 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
  • 如果这个过程 结果为 1,那么这个数就是快乐数。

示例:

输入:n = 19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1

重要结论:在数字各位平方和相加,最终只有两种情况:1、变成1;2、进入循环;而各位数字平方和不可能趋近无限大。以下是来自LeetCode高手的证明过程:

在这里插入图片描述

3.2 丑数

定义:

  • 对于一个正整数,只包含质因数2、3、5

示例:

输入:n = 6
输出:true
解释:6 = 2 * 3

思路:对n反复除以2,3,5看能否被整除。

class Solution {
    public boolean isUgly(int n) {
        if (n <= 0) {
            return false;
        }
        int[] factors = {2, 3, 5};
        for (int factor : factors) {
            while (n % factor == 0) {
                n /= factor;
            }
        }
        return n == 1;
    }
}

4、Tips

4.1 超出时间限制

改进算法,可能需要减少循环的次数。以下方法可以考虑:

  • 采用HashMap,HashMap的key不允许相同的值,利用这一特性在某些场景下可以减少循环次数。同时HashMap有以下重要方法:
Map<Integer, Integer> map = new HashMap<Integer, Ingeger>();
……
map.containsKey(num);//是否存在key,值为num
map.containsValue(num);//是否存在value,值为num

4.2 简化String的计算量

有些题目代码没有问题,却跑不通个别用例。这时候对于String类可以考虑以下优化方法来减少计算量:

String s = ……;
String t = ……;
char[] str1 = s.toCharArray();
char[] str2 = t.toCharArray();
Arrays.sort(str1);//得到经过排序的char数组
Arrays.sort(str2);
Arrays.equals(str1, str2);//直接判断两个数组是否相同

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/886653.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【腾讯云Cloud Studio实战训练营】Cloud Studio + iPad,让代码之舞飞扬在指尖

Cloud Studio iPad&#xff0c;让代码之舞飞扬在指尖 妙手偶得&#xff0c;开启神奇之旅立即反馈&#xff0c;一切尽在掌握版本控制&#xff0c;简单易用MetaWork 协作&#xff0c;摸鱼变得不再轻松 ​一直以来&#xff0c;开发者大多都习惯在电脑端开发&#xff0c;而iPad只是…

Swift 基础

工程目录 请点击下面工程名称&#xff0c;跳转到代码的仓库页面&#xff0c;将工程 下载下来 Demo Code 里有详细的注释 点击下载代码&#xff1a;swift-01

windows 删除桌面右键菜单多余项

Step1&#xff1a;打开注册表 winr输入 regedit Step2&#xff1a;输入以下路径&#xff0c;跳转到相应位置 计算机\HKEY_CLASSES_ROOT\Directory\Background\shell 即可查看当前所有的右键选项&#xff0c;如下图所示 Step3&#xff1a;删除不需要的选项 直接删掉相应的文…

javaScript:数组检测

目录 一.前言 二.数组检测方法 1.every&#xff08;&#xff09; 2.some&#xff08;&#xff09; 3.filter&#xff08;&#xff09; 一.前言 数组检测是指在编程中对数组进行验证和检查的过程。数组检测可以涉及以下方面&#xff1a; 确定数组的存在&#xff1a;在使用数…

NLP中的RNN、Seq2Seq与attention注意力机制

目录 NLP自然语言处理 的RNN、Seq2Seq与attention注意力机制 RNN循环神经网络 前馈网络入门 前馈网络 循环网络 多层感知器架构示例 循环神经网络的运作原理 展开 RNN seq2seq模型 Attention&#xff08;注意力机制&#xff09; 总结 引用 NLP自然语言处理 的RNN、…

Vite更新依赖缓存失败,强制更新依赖缓存

使用vitets开发一段时间了&#xff0c;感觉并不是想象中的好用&#xff0c;特别是出现些稀奇古怪的问题不好解决&#xff0c;比如下面这个问题 上午9:50:08 [vite] error while updating dependencies: Error: ENOENT: no such file or directory, open E:/workspace-dir/node…

2023年备受欢迎的5款团队任务管理工具

任务管理是团队协作的重要环节&#xff0c;选择合适的团队任务管理软件可以提高工作效率、明确责任分工、加强沟通协作。在互联网领域&#xff0c;有许多好用的团队任务管理软件可供选择。下面介绍5款比较知名的团队任务管理软件&#xff0c;并从互联网场景的相关背景内容上进行…

懵了,面试官问我Redis怎么测,直接凉了...

前言 有些朋友来问我&#xff0c;redis要怎么测试&#xff1f;首先我们需要知道&#xff0c;redis是什么&#xff1f;它能做什么&#xff1f; redis是一个key-value类型的高速存储数据库。 redis常被用做&#xff1a;缓存、队列、发布订阅等。 所以&#xff0c;“redis要怎么测…

JavaEE初阶:多线程 - Thread 类的基本用法

上次我们了解了多线程的五种创建方法&#xff0c;今天来学习Thread的基本用法。 目录 run和start Thread常见的构造方法 Thread的几个常见属性 后台线程 是否存活 线程终止 1.使用标志位 2.使用Thread自带的标志 等待线程 run和start 首先需要理解Thread的run和star…

小程序商品如何设置指定的配送规则

小程序配送规则包括商品是否包邮、包邮金额、起总金额、计费方式、配送区域等&#xff0c;这些规则直接影响到商家的运营和用户的购物体验。下面将详细介绍如何给商品设置配送规则。 1. 添加配送规则。商家在配送设置->配送规则&#xff0c;添加配送规则。配送规则支持的功…

openpnp - 做一个抛料盒

文章目录 openpnp - 做一个抛料盒概述效果图零件 - 抛料盒主体零件 - 磁铁仓盖板END openpnp - 做一个抛料盒 概述 8mm散料飞达做回来了, 上面用的长方形磁铁(4x6x10mm)透过0.8mm的3D打印薄壁, 和固定铁板的吸力很大, 用磁力固定的非常好. 正好缺一个抛料盒, 就按照散料飞达的…

Vue中拖动排序功能,引入SortableJs,前端拖动排序。

背景&#xff1a; 作为一名前端开发人员&#xff0c;在工作中难免会遇到拖拽功能&#xff0c;分享一个github上一个不错的拖拽js库&#xff0c;能满足我们在项目开发中的需要&#xff0c;支持Vue和React&#xff0c;下面是我在vue后台项目中中使用SortableJS的使用详细流程&am…

现代C++:使用 shared_from_this 防止 this 提前被释放

首先概括一下shared_from_this的作用&#xff1a;可以在类的成员函数中直接通过this得到指向当前所在对象的shared_ptr的智能指针&#xff0c;具体操作如下。 使用方法 设需要提供shared_from_this方法的类为C0定义为类&#xff0c;首先需要将C0定义为 std::enable_shared_fr…

NCAA棒球介绍·棒球1号位

NCAA棒球介绍 1. NCAA简介 NCAA&#xff08;National Collegiate Athletic Association&#xff09;的历史与发展 NCAA&#xff0c;这个拥有94年悠久历史的体育联盟&#xff0c;从一所校际体育比赛&#xff0c;发展成为世界上最大的大学体育组织&#xff0c;NCAA的发展历程充…

.NET Core发布到IIS

项目介绍 1、开发工具Visual Studio 2017&#xff0c;语言C#&#xff0c;SQL SERVER&#xff0c;WIN10 2、本地IIS&#xff0c;手机上或其他用户在和本地在同一个局域网内访问,同时要把防火墙关掉 3、IIS全名Internet Information Services&#xff0c;用来发布网站 先决条件 安…

[UE4][C++]使用qrencode动态生成二维码

一、使用CMake编译x64版本qrencode 下载地址 GitHub - fukuchi/libqrencode: A fast and compact QR Code encoding libraryA fast and compact QR Code encoding library. Contribute to fukuchi/libqrencode development by creating an account on GitHub.https://github.…

同创永益郑阳|与数智化共舞·业务稳定性保障新动力

2023年8月2日&#xff0c;由北大创新评论主办的2023 Inno China中国产业创新大会-保险产业创新论坛在京举办。本次论坛由同创永益、青牛软件、DaoCloud道客联合主办&#xff0c;INNO创新家、产业集群发展提供战略支持&#xff0c;未名数创承办&#xff0c;邀请到了学术专家、行…

抖音怎样发才有更多人看?四川玖璨电商

抖音是一款非常受欢迎的短视频应用程序&#xff0c;如果你想让更多人看到你的视频&#xff0c;那么你需要学习如何正确地使用抖音平台。在本文中&#xff0c;我们将提供一些有用的建议&#xff0c;以帮助你增加你的观众数量&#xff0c;让你的视频更加受欢迎。 1. 精心选择主题…

配置/var/tmp/fstab 权限/配置用户账户/查找文件/查找字符串

目录 配置/var/tmp/fstab 权限 配置用户账户 查找文件 查找字符串 创建归档 配置/var/tmp/fstab 权限 配置文件权限&#xff0c;将文件 /etc/fstab 复制到 /var/tmp/fstab 。配置 /var/tmp/fstab 的权限以满足 如下条 件&#xff1a; /var/tmp/fstab 属于 root 用户…