首页 文章 精选 留言 我的

精选列表

搜索[leetcode],共439篇文章
优秀的个人博客,低调大师

Leetcode打卡 | No.25 k 个一组翻转链表

No.25 k 个一组翻转链表 给出一个链表,每k个节点一组进行翻转,并返回翻转后的链表。 k是一个正整数,它的值小于或等于链表的长度。如果节点总数不是k的整数倍,那么将最后剩余节点保持原有顺序。 示例 : 给定这个链表:1->2->3->4->5 当k= 2 时,应当返回:2->1->4->3->5 当k= 3 时,应当返回:3->2->1->4->5 说明 : ●你的算法只能使用常数的额外空间。●你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。 特意留白一行 ,因为小詹做了两个多小时 ,还是没做出来 。。。。。。然后也就不想挣扎了 ,看了别人的代码 ,刷题这个东西 ,不能停啊 !不进则退 。 简单分析下思路 : ●链表长度应该是大于给定值 k 的 ,可以分两种情况进行处理 。 ●一种是连续 k 个节点做翻转 ,之后将多个链表片段进行整合 。 ●另一种是链表结尾多出的几个节点 ,不够 k 个节点的那部分保留不做翻转 。 以下是讨论区的代码 ,验证可行 。说实话 ,小詹自己是没想到 ,小詹自己想到的是相邻两个翻转 ,依次往后 ,但是没能实现 。。下边代码建议自己假设一个案例复现 ,顺着思路走能看懂 ,但是自己写就是另一回事了 ……手生了哎 原文发布时间为:2018-09-19 本文来自云栖社区合作伙伴“小詹学Python”,了解相关信息可以关注“小詹学Python”。

优秀的个人博客,低调大师

「判断路线成圈」python之leetcode刷题|005

题目 初始位置 (0, 0) 处有一个机器人。给出它的一系列动作,判断这个机器人的移动路线是否形成一个圆圈,换言之就是判断它是否会移回到原来的位置。 移动顺序由一个字符串表示。每一个动作都是由一个字符来表示的。机器人有效的动作有 R(右),L(左),U(上)和 D(下)。输出应为 true 或 false,表示机器人移动路线是否成圈。 示例 1: 输入: "UD" 输出: true 示例 2: 输入: "LL" 输出: false 解答 判断上下,和左右分别相加为零不就行了吗 class Solution(object): def judgeCircle(self, moves): """ :type moves: str :rtype: bool """ x = 0 y = 0 for i in moves: if i == 'U': x += 1 elif i == 'D': x -= 1 elif i == 'L': y += 1 else: y -= 1 return x == y == 0 当然这种方法肯定是最笨的方法,看一下结果,打败36.72%的提交者,看一下网友代码: class Solution(object): def judgeCircle(self, moves): """ :type moves: str :rtype: bool """ return moves.count('U') == moves.count('D') and moves.count('L') == moves.count('R') 一行解决,不得不说真厉害。

优秀的个人博客,低调大师

java之-------LeetCode--------784. 字母大小写全排列

public List<String> letterCasePermutation(String S) { List<String> res = new LinkedList<>(); dfs("", S, res, 0); return res; } public void dfs(String pre, String S, List<String> res, int index) { System.out.println(pre+"-----------"); // 判断结束的条件,因为没有for循环所以只能这么判断 if (index == S.length()) res.add(pre); else { //System.out.println(pre + "//////////////" + index); char ch = S.charAt(index); // 指定这是一个字母啊,就是数字, if (!Character.isLetter(ch)) dfs(pre + ch, S, res, index + 1); else { // System.out.println("xiaoxie"); // 将字符参数转化为小写的 ch = Character.toLowerCase(ch); dfs(pre + ch, S, res, index + 1); // System.out.println("===========" + index); // 将字符参数转化为大写的 ch = Character.toUpperCase(ch); dfs(pre + ch, S, res, index + 1); } } }

优秀的个人博客,低调大师

leetcode算法题解(Java版)-14-第k小数问题

一、第k小数问题 题目描述 There are two sorted arrays A and B of size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)). 思路 题目要求在O(log(m+n))时间内完成,可以转换为找到假设两个数组合并后的第(m+n)/2小的数。 这里先忽略奇偶问题,具体实现代码中会有不同。先假设A和B中的数都大于k/2,比较A[k/2-1]和B[k/2-1](减1是因为数组下标从零开始)如果A[k/2-1] 代码 public class Solution { public double findMedianSortedArrays(int A[], int B[]) { //奇偶数不会有影响,最后中位数就是平均值 int m = A.length,n = B.length; int l = (m+n+1)/2; int r = (m+n+2)/2; return (findKthNum(A,B,0,0,l)+findKthNum(A,B,0,0,r))/2.0; } private double findKthNum(int [] A,int [] B,int Astart,int Bstart,int k){ int lenA = A.length; int lenB = B.length; if(Astart>=lenA){ return B[Bstart+k-1]; } if(Bstart>=lenB){ return A[Astart+k-1]; } if(k==1){ return Math.min(A[Astart],B[Bstart]); } int minA = Integer.MAX_VALUE; int minB = Integer.MAX_VALUE; if(Astart+k/2-1<A.length){ //如果这里超过了A数组的范围,那就说明A中有将A、B合并后一半以上的 //数,也就是说中位数肯定在A中。那后面的minB<minA(MAX_VALUE),就会成立,从而舍弃B中的前一些无关的数 minA = A[Astart+k/2-1]; } if(Bstart+k/2-1<B.length){ minB = B[Bstart+k/2-1]; } if(minA<minB){ return findKthNum(A,B,Astart+k/2,Bstart,k-k/2); } else{ return findKthNum(A,B,Astart,Bstart+k/2,k-k/2); } } } 二、map映射 题目描述 Given an array of integers, find two numbers such that they add up to a specific target number. The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based. You may assume that each input would have exactly one solution. Input: numbers={2, 7, 11, 15}, target=9Output: index1=1, index2=2 思路 给一列数,给一个目标值,找出数列中两个数和为这个值的下标。因为数没有排序,可以考虑用map来构建数值和下标的映射,更狠一点,在遍历数组的同时,用map构建目标值减去当前这个数的值与当前下标的映射,然后对每一个遍历到的数判断是否已存在在map中。 代码 import java.util.HashMap; public class Solution { public int[] twoSum(int[] numbers, int target) { int n = numbers.length; int [] res = new int [2]; HashMap<Integer,Integer> map = new HashMap<Integer,Integer>(); for(int i=0 ;i<n;i++){ if(map.containsKey(numbers[i])){ res[0]=map.get(numbers[i])+1; res[1]=i+1; break; } else{ map.put(target-numbers[i],i); } } return res; } } 三、动态规划 题目描述 You are climbing a stair case. It takes n steps to reach to the top. Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top? 思路 题目提示了用动态规划来解,那自然想到从step 1,2,3,.。于是慢慢推了看看,看是否能得到状态转移方程。写了几个,发现:dp[i]=dp[i-1]+dp[i-2]; 代码 public class Solution { public int climbStairs(int n) { int [] dp = new int[n+2]; dp[1]=1; dp[2]=2; for(int i=3;i<=n;i++){ dp[i]=dp[i-1]+dp[i-2]; } return dp[n]; } } //优化一下空间复杂度 public class Solution { public int climbStairs(int n) { if(n<=2){ return n; } int one_step_before=2; int two_step_before=1; for(int i=3;i<=n;i++){ int cur = one_step_before+two_step_before; two_step_before = one_step_before; one_step_before = cur; } return one_step_before; } }

优秀的个人博客,低调大师

leetcode算法题解(Java版)-8-动态规划+状态压缩

一、树 题目描述 Given a binary tree struct TreeLinkNode { TreeLinkNode *left; TreeLinkNode *right; TreeLinkNode *next; } Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set toNULL. Initially, all next pointers are set toNULL. Note: You may only use constant extra space. You may assume that it is a perfect binary tree (ie, all leaves are at the same level, and every parent has two children). For example,Given the following perfect binary tree, 1 / \ 2 3 / \ / \ 4 5 6 7 After calling your function, the tree should look like: 1 -> NULL / \ 2 -> 3 -> NULL / \ / \ 4->5->6->7 -> NULL 思路 题目的意思可能看文字有点不明白,没关系!看明白它给的两个图就行了,就是图上描绘的意思。 这道题有点像链表,二叉树中多了个链表,其实解法也应该往链表上去想,一般考虑用两个指针一个当前的,控制外部循环,一个是移动的,控制内部小循环。二叉树不断往下走,一边走一边从左向右实现同一层节点之间链表的链接 代码 /** * Definition for binary tree with next pointer. * public class TreeLinkNode { * int val; * TreeLinkNode left, right, next; * TreeLinkNode(int x) { val = x; } * } */ public class Solution { public void connect(TreeLinkNode root) { if(root==null){ return; } TreeLinkNode p=root; TreeLinkNode q=root; while(p.left!=null){ q=p; while(q!=null){ q.left.next=q.right; if(q.next!=null){ q.right.next=q.next.left; } q=q.next; } p=p.left; } return; } } 二、动态规划 题目描述 Given a string S and a string T, count the number of distinct subsequences of T in S. A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie,"ACE"is a subsequence of"ABCDE"while"AEC"is not). Here is an example:S ="rabbbit", T ="rabbit" Return3. 思路 又是典型的动态规划~~重新的复习了一下: 动态规划: 参考:CSDN 动态规划解题的一般思路: 将原问题分解为子问题:子问题和原问题类似 确定状态:即是dp数组,存储了子问题的状态 确定初始状态(边界)的值:这个需要想一下,但其实一般都是由套路的,比如都是0或者都是1。实在不知道,可以用几个值试一试 写出状态转移方程 动态规划解题的特点: 问题具有最优子结构:如果原问题的最优解也是子问题的最优解。 无后效性:当前的状态之和它之前的某些特定位置的状态有关,和路径等无关,即后来产生的值不会影响前面已经确定的值。 回到题目中来 好了,那么来看这一道题:首先可以分解为子问题,而且子问题的最优解也是原问题的最优解。 dpi就是所谓的子问题,也是状态空间,表示S[0~i-1]中包含的T[0~j-1]的subsequences(这个定义看题目)数目。然后具体分析请看代码 推荐在草稿画出dp数组,一边看代码一边填dp。 代码 public class Solution { public int numDistinct(String S, String T) { int lenS=S.length(); int lenT=T.length(); if(lenS==0||lenT==0){ return 0; } int row=lenS+1; int col=lenT+1; int [][] dp=new int [row][col]; for(int i=1;i<col;i++){ dp[0][i]=0; } for(int j=0;j<row;j++){ dp[j][0]=1; } for(int i=1;i<row;i++){ //这里在纸上画字符串数组分析的时候,把字符串的下表可以从“1”开始,便于思维理解 for(int j=1;j<col;j++){ if(S.charAt(i-1)==T.charAt(j-1)){ dp[i][j]=dp[i-1][j-1]+dp[i-1][j];//这里可能稍微难理解, //要记住这一步的目的是解决字符串可以是不连续的,只要满足在原来串中顺序不变即可称为subsequence //结合这个区想这一步为啥这么相加,就能理解了,我是用这个笨方法想的。。。 } else{ dp[i][j]=dp[i-1][j];//既然S[i-1]和T[j-1]不一样,那么不妨不要S[i], //可不能也不要T[j]噢,因为我们的目标是找到S中包含T的所有subsequences } } } return dp[row-1][col-1]; } } 状态压缩+细节优化过的代码详细见代码注释,动态规划一般都是可以压缩一下状态的。 public class Solution { public int numDistinct(String S, String T) { int lenS=S.length(); int lenT=T.length(); if(lenS==0||lenT==0){ return 0; } int col=lenT+1; int row=lenS+1; int dp[]=new int[col]; for(int i=0;i<col;i++){ if(i==0){ dp[i]=1; continue; } dp[i]=0; } for(int i=1;i<row;i++){ for(int j=j=Math.min(i,col-1);j>0;j--){ //其实这里还能再优化,写成 "j=Math.min(i,col-1)" //因为S[0~i]不可能包含长度比他大的T[0~j] if(S.charAt(i-1)==T.charAt(j-1)){ dp[j]=dp[j-1]+dp[j]; } else{ dp[j]=dp[j]; } } } return dp[col-1]; } }

优秀的个人博客,低调大师

leetcode算法题解(Java版)-6-链表,字符串

一、字符串处理 题目描述 Given an integer, convert it to a roman numeral. Input is guaranteed to be within the range from 1 to 3999. 思路 把数字转化为罗马符号,根据罗马符号的规律,可以先用map来存储一下。之后把每一位添加到所求中去。 语法点:StringBuffer是字符缓冲区,是可以修改字符长度的,最后要用sb.toString()去返回缓冲区的字符串 代码 //!COPY public class Solution { public String intToRoman(int num) { String[][] map={ {"","I","II","III","IV","V","VI","VII","VIII","IX"}, {"","X","XX","XXX","XL","L","LX","LXX","LXXX","XC"}, {"","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"}, {"","M","MM","MMM"} }; StringBuffer sb=new StringBuffer(); sb.append(map[3][num/1000%10]); sb.append(map[2][num/100%10]); sb.append(map[1][num/10%10]); sb.append(map[0][num%10]); return sb.toString(); } } 二、链表 题目描述 You are given two linked lists representing two non-negative numbers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) Output: 7 -> 0 -> 8 思路 链表的题,虽然题目说存放的数字是反过来的,但是完全可以把加法也”反过来“,也就是说从”左到右“相加。 链表的题,一般都应该设置一个头指针head(里面什么也不存放,只是用来记住链表的头) 代码 /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ public class Solution { public ListNode addTwoNumbers(ListNode l1, ListNode l2) { if(l1==null){ return l2; } if(l2==null){ return l1; } ListNode head=new ListNode(0); ListNode p=head; int tem=0; while(l1!=null||l2!=null||tem!=0){ if(l1!=null){ tem+=l1.val; l1=l1.next; } if(l2!=null){ tem+=l2.val; l2=l2.next; } p.next=new ListNode(tem%10); p=p.next; tem/=10; } return head.next; } } 三、最长无重复字符子串 题目描述 Given a string, find the length of the longest substring without repeating characters. For example, the longest substring without repeating letters for "abcabcbb" is "abc", which the length is 3. For "bbbbb" the longest substring is "b", with the length of 1. 思路 水题渐渐做完了,开始碰到的题有难度了。这题用到了所谓的滑动窗口法:从左到右滑动,如果碰到了在左边界内且出现过的字符,那就将左边界移动到之前的那个字符的下一位,刷新求最大即可。 还看到一位大神的神解法,代码很简洁,思想其实也是一样的:从左到右滑动,记录每一个字符上一次出现的位置,在第i位时比较当前字符的上一次出现的位置和左边界,刷新当前左边界。 代码1 import java.util.HashMap; public class Solution { public int lengthOfLongestSubstring(String s) { HashMap <Character,Integer> map=new HashMap<>(); int len=s.length(); if(s==null||len==0){ return 0; } int res=0; int l=0; for(int i=0;i<len;i++){ char c=s.charAt(i); if(map.containsKey(c)){ l=Math.max(l,map.get(c)+1); } res=Math.max(res,i-l+1); map.put(c,i); } return res; } } 代码2 import java.util.HashMap; public class Solution { public int lengthOfLongestSubstring(String s) { HashMap<Character,Integer> map=new HashMap<>(); int len = s.length(); if(s==null||len==0){ return 0; } for(int i=0;i<len;i++){ map.put(s.charAt(i),-1); } int l=-1; int res=0; for(int i=0;i<len;i++){ char c=s.charAt(i); l=Math.max(l,map.get(c)); res=Math.max(res,i-l); map.put(c,i); } return res; } }

优秀的个人博客,低调大师

leetcode算法题解(Java版)-2-最长回文子串

一、int数字反转 题目描述Reverse digits of an integer. Example1: x = 123, return 321Example2: x = -123, return -321 思路: 题目很简单,需要注意的是:int型是32位的。1000000003 反转后就超了!所以需要包装类Integer中的最大值和最小值 小技巧:为了实现反转,可以先把符号保存到flag中。 代码: public class Solution { public int reverse(int x) { int res=0; int flag=x>0?1:-1; x=x*flag; while(x>0){ res=10*res+x%10; x/=10; } res=res*flag; if(res>Integer.MAX_VALUE){ res=Integer.MAX_VALUE; } if(res<Integer.MIN_VALUE){ res=Integer.MIN_VALUE; } return (int)res; } } 二、简单模拟、StringBuffer类 题目描述 The string"PAYPALISHIRING"is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility) P A H N A P L S I I G Y I R And then read line by line:"PAHNAPLSIIGYIR" Write the code that will take a string and make this conversion given a number of rows: string convert(string text, int nRows); convert("PAYPALISHIRING", 3)should return"PAHNAPLSIIGYIR". 思路: 这题考到了StringBuffer类,虽然是将原字符“Z“字型排开,然后按每行输出得到结果。观察发现:从上到下(0~nRows),然后再从下到上(nRows-2~0),依次把字符添加到每行对应的sb后面。最后再按行输出就行。 语法点:sb.append(char c);sb.toString();sb.length;s.charAt(int index);s.length(); 代码: public class Solution { public String convert(String s, int nRows) { if(s==null||s.length()<=0||nRows<=1){ return s; } StringBuffer [] sb=new StringBuffer[nRows]; for(int i=0;i<nRows;i++){ sb[i]=new StringBuffer(); } int len=s.length(); int tot=0; while(tot<len){ for(int i=0;i<nRows&&tot<len;i++){ sb[i].append(s.charAt(tot++)); } for(int j=nRows-2;j>0&&tot<len;j--){ sb[j].append(s.charAt(tot++)); } } for(int i=1;i<nRows;i++){ sb[0].append(sb[i]); } return sb[0].toString(); } } 三、最长回文子串 题目描述 Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring. 思路 中间扩散法:因为回文串是中心对称的。不妨找到回文串的中心,往两边扩散来看是否符合回文串定义。奇数:一个中心字符;偶数:两个中心字符 dp大法:设置一个dp状态数组,dp(i,j)=true如果子串i~j是回文串,那么子串i-1~j+1是不是回文串跟i~j有关,所以可以用dp。状态转移方程:dp(i,j)=(s[i]==s[j]&&dp(i+1,j-1)) 代码:中间扩散: public class Solution { public String longestPalindrome(String s) { if(s==null||s.length()<=1){ return s; } int len=s.length(); int beg=0; int ans=0; //odd for(int i=1;i<len;i++){ int m=i-1; int n=i+1; while(m>=0&&n<len&&s.charAt(m)==s.charAt(n)){ if(n-m+1>ans){ ans=n-m+1; beg=m; } m--; n++; } } //even for(int i=0;i<len;i++){ int m=i; int n=i+1; while(m>=0&&n<len&&s.charAt(m)==s.charAt(n)){ if(n-m+1>ans){ ans=n-m+1; beg=m; } m--; n++; } } if(beg==0&&ans==1){ return s.charAt(0)+""; } return s.substring(beg,beg+ans); } } dp大法: public class Solution { public String longestPalindrome(String s) { int len=s.length(); if(len<2||s==null){ return s; } boolean [][] dp=new boolean [len][len]; int maxlen=0; int beg=0; for(int i=0;i<len;i++){//dp解题,初始化dp状态数组 dp[i][i]=true; } for(int i=0;i<len;i++){ for(int j=0;j<i;j++){ if(s.charAt(i)==s.charAt(j)){ if(j+1<len&&i-1>=0&&(dp[j+1][i-1]==true||i-j==1)){//注意!i-j==1小细节,一开始不过就是因为没有考虑它 dp[j][i]=true; if(maxlen<i-j+1){ maxlen=i-j+1; beg=j; } } } } } if(maxlen==0&&beg==0){ return s.charAt(0)+""; } return s.substring(beg,beg+maxlen); } }

优秀的个人博客,低调大师

1700人点反对的LeetCode问题,是因为太难了吗?

云栖号资讯:【点击查看更多行业资讯】在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来! 这题的难度是Medium,通过率是1/3左右,也是一道踩多捧少的题,一共有737个点赞,1703个反对。老实讲我觉得反对得不冤,我先卖个关子,等会来详细聊聊它为什么会被踩。 题意 题目会给定一个字符串,表示一个Unix系统下的文件路径,这个路径当中会包含一些路径的计算, 要求我们返回简化之后的结果。 在Unix系统下用/来分隔文件夹,比如/home/download/file.txt。在这个路径当中支持简单的运算,比如.表示当前文件夹。所以如果我们当前终端在download这个文件夹下,我们要访问file.txt文件,可以使用相对路径./file.txt即可。除此之外,还包括..操作。..表示当前文件夹的上层文件夹。 比如如果我们在download文件夹下,当我们运行cd ..,那么我们就会返回到download文件夹的上层,也就是home文件夹下。我们是可以把..和.嵌入在文件路径中使用的。比如说/home/download/../download/file.txt也是合法的,中间由于我们嵌入了..所以会返回到download的上层也就是home,然后再进入download。虽然这样很费劲,但是是合法的。只要你愿意,可以不停地利用..回到上层,来回穿梭。 我们要返回的是这个路径简化之后的版本也就是:/home/download/file.txt 我们来看几个案例: Input: "/home/"Output: "/home"Explanation: Note that there is no trailing slash after the last directory name.Input: "/../"Output: "/"Explanation: Going one level up from the root directory is a no-op, as the root level is the highest level you can go.Input: "/a/../../b/../c//.//"Output: "/c" 题解 这题其实也是模拟题,不过相比之前我们做过的模拟题难度要小上很多。这道题的思路还是蛮明显的,由于存在..和.的操作,我们需要记录下来访问的路径,在..向上移动的时候把之前的文件夹抛弃掉。 举个例子,a/b/../b/d/e 我们在b之后使用了..回到了a,然后我们再次进入b往下。显然这里由于..导致b在路径当中出现了两次,这是多余的。我们需要在..回到上层的时候把b抛弃掉。对于.操作来说,由于它就表示当前路径,所以对于答案并不会影响,我们直接忽略它的存在即可。 理解了这个思路之后,实现是非常简单的,我们只需要根据/将字符串分段。每一段当中除了.和..之外就是文件夹的名称,我们用一个list去存储从上到下的经过的文件夹,遇见..就将最后一个添加的元素抛弃。最后用/将它们join在一起即可,唯一需要注意的是,当我们已经到了顶层的时候,如果我们继续执行..并不会报错,而是会停留在原地。所以我们需要特殊判断这种情况,除此之外就几乎没有难度了。 代码非常简单,只有10行左右。 总结 到这里,关于题解的部分就结束了。 我们回到标题当中的问题,为什么我会有这样的感受呢?是因为这道题我做过两次,上一次做的时候用的是C++。由于C++的string类型不支持split,所以我需要自己进行split处理。整个的计算过程要复杂得多,我放一下C++的AC代码大家自己感受一下就知道了,简直不是一个次元的。 我说这些的重点并不是吐槽C++这门语言有多么落后,或者是证明Python有多么强大。不同的语言有不同的诞生背景,也有不同的强项,这个是很自然的。这题最主要的问题是不应该出这种因为语言本身的特性带来巨大差异的问题,在正规比赛当中出这样的问题一定是会被疯狂吐槽的。 举个例子,比如Java当中有大整数类BigInter,可以用来代替高精度算法来处理超过int64范围的大整数。如果有出题人出了一道非常复杂的大整数问题,那么使用Java的选手使用BigInter(算法比赛一般不允许使用Python),三两行代码就可以轻松AC,而C++选手却需要些上百行代码来实现高精度计算,这显然是不公平的。所以acm比赛当中,出题人一定会尽量避免这种语言特性差异巨大的问题,大概这也是这题遭黑的原因吧。 【云栖号在线课堂】每天都有产品技术专家分享!课程地址:https://yqh.aliyun.com/live 立即加入社群,与专家面对面,及时了解课程最新动态!【云栖号在线课堂 社群】https://c.tb.cn/F3.Z8gvnK 原文发布时间:2020-05-27本文作者:承志本文来自:“掘金”,了解相关信息可以关注“掘金”

优秀的个人博客,低调大师

LeetCode 21:合并两个有序链表 Merge Two Sorted Lists

将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists. 示例: 输入:1->2->4, 1->3->4 输出:1->1->2->3->4->4 解题思路: 迭代和递归都能解题。无非是依次将两个链表每个节点的值对比,取出值较小的节点,添加到新链表末尾。然后继续比较两个链表,直到其中一个链表遍历完成,此时另一个链表剩余所有节点直接添加到新链表之后即可。其逻辑为: 原链表:1->2->4->null,1->3->4->5->6->null依次对比节点值,取出各自头节点:1 = 1值相同取出一个节点 1,组成新链表:1此时原链表:2->4->null,1->3->4->5->6->null 对比头节点值:2 > 1取出 1 节点,添加到新链表末尾:1->1此时原链表:2->4->null,3->4->5->6->null 对比头节点值:2 < 3取出 2 节点,添加到新链表末尾:1->1->2此时原链表:4->null,3->4->5->6->null .......依次类推,直到其中一个原链表为空时: 原链表:null,4->5->6->null新链表:1->1->2->3->4这时其中一个原链表已经为空,则直接将另一个原链表添加到新链表末尾即可:1->1->2->3->4->4->5->6->null 迭代法: 迭代法需要注意:先判断原链表是否为空;对比原链表第一个节点值的大小,选择较小一个作为新链表的头节点。之后才能按上述逻辑执行。 如果添加一个虚拟节点作为头节点,则无需上述条件,但应当返回虚拟节点的下一个节点。 Java: class Solution { public ListNode mergeTwoLists(ListNode l1, ListNode l2) { ListNode head = new ListNode(-1);//新建虚拟头节点 ListNode cur = head;//当前节点指向虚拟头节点 while (l1 != null && l2 != null) {//循环条件为链表都不为空 if (l1.val < l2.val) {//比较头节点的值的大小 cur.next = l1;//当前节点连接到节点值较小的一个 l1 = l1.next;//刷新原链表头节点 cur = cur.next;//刷新当前节点 } else { cur.next = l2; l2 = l2.next; cur = cur.next; } } if (l1 == null) cur.next = l2;//选择另外一个不为空的原链表,连接到新链表末尾 else cur.next = l1; return head.next;//返回虚拟头节点的下一个节点,即真实头节点 } } Python3: class Solution: def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode: head = ListNode(-1) cur = head; while l1 and l2: if l1.val <= l2.val: cur.next = l1 cur = cur.next l1 = l1.next else: cur.next = l2 cur = cur.next l2 = l2.next if l1: cur.next = l1 else: cur.next = l2 return head.next 递归法: 递归基线条件为:原链表其中之一遇到空节点。返回值为:另一个链表剩余部分的头节点。 递归判断头节点的值的大小,取小的节点添加到新链表之后。将剩余链表传回递归函数。 Java: class Solution { public ListNode mergeTwoLists(ListNode l1, ListNode l2) { if (l1 == null) return l2;//基线条件 if (l2 == null) return l1;//基线条件 ListNode head; if (l1.val <= l2.val) {//选择节点值较小的节点 head = l1;//刷新头节点 head.next = mergeTwoLists(l1.next, l2);//剩余链表作为参数传入递归函数 } else { head = l2; head.next = mergeTwoLists(l1, l2.next); } return head; } } Python3: class Solution: def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode: if not l1: return l2 if not l2: return l1 if l1.val <= l2.val: head = l1 head.next = self.mergeTwoLists(l1.next, l2) else: head = l2 head.next = self.mergeTwoLists(l1, l2.next) return head 欢迎关注公.众号:爱写Bug

优秀的个人博客,低调大师

LeetCode 485:连续最大1的个数 Max Consecutive Ones(python java)

公众号:爱写bug 给定一个二进制数组, 计算其中最大连续1的个数。 Given a binary array, find the maximum number of consecutive 1s in this array. 示例 1: 输入: [1,1,0,1,1,1] 输出: 3 解释: 开头的两位和最后的三位都是连续1,所以最大连续1的个数是 3. 注意: 输入的数组只包含 0 和1。 输入数组的长度是正整数,且不超过 10,000。 Note: The input array will only contain 0 and 1. The length of input array is a positive integer and will not exceed 10,000 解题思路: ​ 记录一个指针向右移动,用一个数记录1的个数,遇1就累加1,遇0就倒置为0。具体见 Java 注释。 Java: class Solution{ public int findMaxConsecutiveOnes(int[] nums) { int temp=0,count=0;//temp记录当前连续1的个数,count记录当前最大连续1的个数 for (int i=0;i<nums.length;i++){//指针右移 if(nums[i]==1){ temp++;//遇1累加1 }else{ if(count<temp){ count=temp;//记录目前最大连续1的个数 } temp=0;//遇0倒置为0 } } return (count>temp)? count:temp;//返回count、temp中较大的数 } } 注意: ​ 返回值必须是count 与temp 中较大的一个。明明已经比较了count和temp,并把较大的赋值给count ,很明显是count 更大,为什么还要比较? ​ 这是因为还有一种输入数组全为1的情况,此时temp一直累加,从未遇到0,所以count自始至终都不可能得到temp的值。 python3: class Solution: def findMaxConsecutiveOnes(self, nums: List[int]) -> int: count=temp=0 for num in nums: if num==1: temp+=1 else: if(count<temp): count=temp temp=0 return count if count>temp else temp

优秀的个人博客,低调大师

Leetcode 498:对角线遍历Diagonal Traverse(python3、java)

对角线遍历 给定一个含有 M x N 个元素的矩阵(M 行,N 列),请以对角线遍历的顺序返回这个矩阵中的所有元素,对角线遍历如下图所示。Given a matrix of M x N elements (M rows, N columns), return all elements of the matrix in diagonal order as shown in the below image.示例: 输入: [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ] 输出: [1,2,4,7,5,3,6,8,9] 解释: 说明: 给定矩阵中的元素总数不会超过 100000 。 思路: ​ 实例输入的二维数组范围均是0~2 ​ 先观察一下遍历规律:(0,0)->(0,1)->(1,0)->(2,0)->(1,1)->(0,2)->(1,2)->(2,1)->(2,2) ​ 数组索引(m,n),两种改变方式1、(m-1,n+1) 2、(m+1,n-1) ​ 数组从(0,0)开始,先是(m-1,n+1) ,(0,0)->(-1,1)此时m=-1,超出范围,m赋值0。然后切换索引改变方式(m+1,n-1),执行两次(0,1)->(1,0)->(2,-1),n赋值0得到(2,0),再次切换为索引改变方式(m-1,n+1)直到下次超出范围(2,0)->(1,1)->(0,2)->(-1,3)。此时m<0且n>2均超出范围,(m+2,n-1),应当优先判断n是否超出范围,执行(m+2,n-1)->(1,2),避免因为m<0再次切换一次索引改变方式。然后正常切换后:(1,2)->(2,1)->(3,0),因为m>2,切换方式并(m-1,n+2) java: class Solution { public int[] findDiagonalOrder(int[][] matrix) { if (matrix.length==0||matrix[0].length==0)return new int[0]; int col=matrix.length,row=matrix[0].length; int nums=col*row,m=0,n=0; int res[]=new int[nums]; boolean flag=true; for(int i=0;i<nums;i++){ res[i]=matrix[m][n]; if(flag){ n+=1; m-=1; }else{ n-=1; m+=1; } if(m>=col){ m-=1; n+=2; flag=true; }else if(n>=row){ n-=1; m+=2; flag=false; } if(m<0){ m=0; flag=false; }else if(n<0){ n=0; flag=true; } } return res; } } 注意点: ​ if (matrix.length==0||matrix[0].length==0)return new int[0];首先判断是否为空数组,另外 matrix.length==0||matrix[0].length==0 判断条件顺序不能颠倒,因为如果 matrix.length==0 后面的 matrix[0].length==0 不会再判断,即返回空数组;但是matrix[0].length==0 在前时,如果输入数组为空,matrix[0] 会报错因为matrix并没有0号索引。 ​ for循环里应当先判断m、n是否大于或等于各自的最大长度,然后执行(m-1,n+2)、(m+2,n-1)。避免出现m、n同时小于0时flag布尔值转换两次的错误。 python: class Solution: def findDiagonalOrder(self, matrix: List[List[int]]) -> List[int]: if(len(matrix)==0 or len(matrix[0])==0): return [] col=len(matrix) row=len(matrix[0]) nums=col*row m=n=0 flag=True res=[] for i in range(nums): res.append(matrix[m][n]) if flag: m-=1 n+=1 else: m+=1 n-=1 if m>=col: m-=1 n+=2 flag=True elif n>=row: m+=2 n-=1 flag=False if m<0: m=0 flag=False elif n<0: n=0 flag=True return res

优秀的个人博客,低调大师

Leetcode724:寻找数组的中心索引(java、python3)

寻找数组的中心索引 给定一个整数类型的数组 nums,请编写一个能够返回数组“中心索引”的方法。 我们是这样定义数组中心索引的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和。 如果数组不存在中心索引,那么我们应该返回 -1。如果数组有多个中心索引,那么我们应该返回最靠近左边的那一个。 示例 1: 输入: nums = [1, 7, 3, 6, 5, 6] 输出: 3 解释: 索引3 (nums[3] = 6) 的左侧数之和(1 + 7 + 3 = 11),与右侧数之和(5 + 6 = 11)相等。 同时, 3 也是第一个符合要求的中心索引。 示例 2: 输入: nums = [1, 2, 3] 输出: -1 解释: 数组中不存在满足此条件的中心索引。 说明: nums 的长度范围为 [0, 10000]。 任何一个 nums[i] 将会是一个范围在 [-1000, 1000]的整数。 起先我的思路是从第一个索引左累加、右累加判断是否想等: import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class Main { public static void main(String[] args) { List<Integer> nums = new ArrayList<>(); int sumLeft=0,sumRight=0; Scanner scan =new Scanner(System.in); while (scan.hasNextInt()){ nums.add(scan.nextInt()); } int numsSize=nums.size()-1; for(int i=1;i<numsSize;i++){ for(int j=0;j<i;j++){ sumLeft+=nums.get(j); } for(int j=numsSize;j>i;j--){ sumRight+=nums.get(j); } if(sumLeft==sumRight){ System.out.println(i); break; }else { sumLeft=sumRight=0; } } if(sumLeft==0){ System.out.println(-1); } } } 做完之后搜一下别人的答案。。。果然被吊打。 解题思路: 参考博客园 左累加没必要从0号索引开始,之前的累加加上下一号索引即可。右累加完全可以算一次总和减去左累加即可。 参考:判断中心索引条件 左侧索引如果和右侧相等,即二倍加左侧累加和+中心索引=总和 java: class Solution { public int pivotIndex(int[] nums) { int sumLeft=0,sum=0; for (int n:nums){ sum = sum + n; } int numsSize=nums.length-1; for(int i=0;i<=numsSize;i++){ if(i==0){ sumLeft=0; }else{ sumLeft+=nums[i-1]; } //左侧索引如果和右侧相等,即二倍左侧加中心索引=总和 if(sumLeft*2+nums[i]==sum){ return i; } } return -1; } } 特别说明一下,索引一定要从0开始到最后一个止,因为题目后中心索引右侧相加可以为0。 java默认模板里int[] nums指从控制台输入int 数组,不需要Arraylist动态构造数组了。 python3 ​ nums即为list动态数组 class Solution: def pivotIndex(self, nums: List[int]) -> int: """ :type nums: int """ sumAll=sum(nums) leftSum=0 for i in range(len(nums)): if(i==0): leftSum=0 else: leftSum+=nums[i-1] #左侧索引如果和右侧相等,即二倍加左侧中心索引=总和 if(leftSum*2+nums[i]==sumAll): return i return -1

优秀的个人博客,低调大师

leetcode算法题解(Java版)-17-图的巧妙用法

一、图 题目描述 Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses. For example, given n = 3, a solution set is: "((()))", "(()())", "(())()", "()(())", "()()()" 思路 看到一个非常有意思的思路,是用图来解释的。值得借鉴。 关键:当前位置的左括号数目<右括号 图:节点:当前位置的左括号和右括号数目即为(x,y)(x>=y)边:从(x,y)->(x+1,y),(x,y)->(x,y+1)注意当x==y时,不存在(x,y)->(x,y+1)这条边 解:从(0,0)出发到(n,n)的全部路径。 上面是大神的思路,敲完后,总结一下:题目要求的是各种输出结果,这种题以后可以往图上考虑考虑。找出题目中的隐含的限制条件作为边界条件,然后确定好当前的状态也就是节点,再确定这个节点到下一个节点的路径,也就是边。 代码 import java.util.ArrayList; public class Solution { public ArrayList<String> generateParenthesis(int n) { ArrayList<String> list = new ArrayList<String>(); help(n,0,0,"",list); return list; } public void help(int n,int x,int y,String tem,ArrayList<String> list){ if(y==n){ list.add(tem); } if(x<n){ help(n,x+1,y,tem+'(',list); } if(x>y){ help(n,x,y+1,tem+')',list); } } } 二、链表 题目描述 Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists. 思路 题目意思感觉没说明白,意思就是把两个有序的链表合并(splice)到一起组成一个有序链表。 开一个空的头节点,或者头指针,搞不清楚。反正明白意思就好,头节点里面不放数值。然后就是循环比较各个节点大小,依次加入新建的链表中。 代码 /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ public class Solution { public ListNode mergeTwoLists(ListNode l1, ListNode l2) { ListNode head = new ListNode(0); ListNode p = head; while(l1!=null&&l2!=null){ if(l1.val<l2.val){ p.next = l1; l1 = l1.next; } else{ p.next = l2; l2 = l2.next; } p = p.next; } if(l1 == null){ p.next = l2; } if(l2 == null){ p.next = l1; } return head.next; } } 三、动态规划 题目描述 Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path. Note: You can only move either down or right at any point in time. 思路 动态规划,老套路,求什么我们就把以什么作为状态数组dp,同样的,先来一个空间复杂度为m*n的,然后再考虑优化空间。 代码 //空间复杂度m*n public class Solution { public int minPathSum(int[][] grid) { int m = grid.length; int n = grid[0].length; if(grid == null){ return 0; } for(int i=0;i<m;i++){ for(int j=0;j<n;j++){ if(i==0&&j>0){ grid[i][j]+=grid[i][j-1]; } if(j==0&&i>0){ grid[i][j]+=grid[i-1][j]; } if(i*j!=0){ grid[i][j]+=Math.min(grid[i-1][j],grid[i][j-1]); } } } return grid[m-1][n-1]; } } import java.util.Arrays; public class Solution { public int minPathSum(int[][] grid) { if(grid == null){ return 0; } int m = grid.length; int n = grid[0].length; int [] dp = new int [n+1]; Arrays.fill(dp,Integer.MAX_VALUE); dp[1]=0;//dp[0]空出来,方便操作 for(int i=0;i<m;i++){ for(int j=0;j<n;j++){ //注意这里dp数组中下标从1开始 //dp[j]表示空间复杂度为m*n的代码中的grid[i][j-1] //dp[j+1]表示grid[i-1][j] dp[j+1]=Math.min(dp[j],dp[j+1])+grid[i][j]; } } return dp[n]; } }

优秀的个人博客,低调大师

「比较含退格的字符串」python之leetcode刷题|008

题目 给定 S 和 T 两个字符串,当它们分别被输入到空白的文本编辑器后,判断二者是否相等,并返回结果。 # 代表退格字符。 示例 1: 输入:S = "ab#c", T = "ad#c" 输出:true 解释:S 和 T 都会变成 “ac”。 示例 2: 输入:S = "ab##", T = "c#d#" 输出:true 解释:S 和 T 都会变成 “”。 示例 3: 输入:S = "a##c", T = "#a#c" 输出:true 解释:S 和 T 都会变成 “c”。 示例 4: 输入:S = "a#c", T = "b" 输出:false 解释:S 会变成 “c”,但 T 仍然是 “b”。 提示: 1 <= S.length <= 200 1 <= T.length <= 200 S 和 T 只含有小写字母以及字符 '#'。 解答 这道题数退栈和出栈的操作,逻辑有点强。这里先要把两个字符串换成没有#的,然后在进行比较即可 class Solution(object): def backspaceCompare(self, S, T): """ :type S: str :type T: str :rtype: bool """ s = '' t = '' for i in S: if i == '#': if s: s = s[:-1] else: s += i for j in T: if j == '#': if t: t = t[:-1] else: t += j return s==t 这里一定要加判断是否字符串s,t为空,因为如果没有这个判断,假如输入的字符串第一个元素为#,x下面执行的代码就要报错。 看一下执行结果 image.png 再看一下排名靠前的代码 class Solution(object): def backspaceCompare(self, S, T): """ :type S: str :type T: str :rtype: bool """ s1 = [] s2 = [] for i in S : if i == '#' : if s1 : s1.pop() else : s1.append( i ) for i in T : if i == '#' : if s2 : s2.pop() else : s2.append( i ) return ''.join(s1 ) == ''.join( s2 ) 这个逻辑更好理解。不说了,继续练习去。

优秀的个人博客,低调大师

「只出现一次的数字」python之leetcode刷题|007

题目 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。 说明: 你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗? 示例 1: 输入: [2,2,3,2] 输出: 3 示例 2: 输入: [0,1,0,1,0,1,99] 输出: 99 解答 这道题是中等难度的题目,刚开始我一看,哎,这么简单,顺手就写了起来 class Solution(object): def singleNumber(self, nums): """ :type nums: List[int] :rtype: int """ for i in nums: if nums.count(i) == 1: return i 运行一看也正确,没啥问题,统计数字嘛,以前也遇见过。 可是当我看运行结果我才知道,这道题不是不仅仅是解出来结果就行了。还要考虑时间复杂度。 看一下我的运行结果 执行结果 可以看到只打败了10%的提交者,虽然解决了问题,可耗时太长,显然不是这道题的最好解决方法。 看看大佬的代码 class Solution(object): def singleNumber(self, nums): """ :type nums: List[int] :rtype: int """ if len(nums) == 1: return nums[0] a = sorted(nums) for i in range(0,len(nums)-1): if a[i] == a[i-1] or a[i] == a[i+1]: continue else: return a[i] return a[-1] 之所以我的代码耗时时间长,是因为每次统计都要遍历一遍列表,大佬的代码只遍历了一次。 再看一个 class Solution(object): def singleNumber(self, nums): """ :type nums: List[int] :rtype: int """ buffer_dict = {x: 0 for x in nums} for x in nums: buffer_dict[x] += 1 for x in buffer_dict.items(): if x[1] == 1: return x[0] 利用字典来做,时间复杂度最小,耗时28ms,目前来说最好的解决方法。

优秀的个人博客,低调大师

leetcode算法题解(Java版)-15-动态规划(斐波那契)

一、二叉树遍历 题目描述 Given a binary tree, determine if it is height-balanced. For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1. 思路 两种思路,都是递归。第一种是递归的判断每个节点的左右子树的深度是否只相差一以内。第二种做了剪枝处理,当判断到一个子树已经不满足时就返回结果。 代码 //思路一 /** * Definition for binary tree * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class Solution { public boolean isBalanced(TreeNode root) { if(root==null){ return true; } if(Math.abs(maxDepth(root.left)-maxDepth(root.right))>1){ return false; } //如果这个节点的左右子树高度差小于等于一,那就递归看它的左右子树节点是否合格 return isBalanced(root.left)&&isBalanced(root.right); } private int maxDepth(TreeNode root){ if(root==null){ return 0; } return Math.max(maxDepth(root.left),maxDepth(root.right))+1; } } //思路二 /** * Definition for binary tree * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class Solution { public boolean isBalanced(TreeNode root) { if(root==null){ return true; } return getHeight(root)!=-1; } private int getHeight(TreeNode root){ if(root==null){ return 0; } int left = getHeight(root.left); if(left==-1){ return -1; } int right = getHeight(root.right); if(right==-1){ return -1; } if(left-right>1||right-left>1){ return -1; } return 1+Math.max(left,right); } } 二、动态规划(斐波那契) 题目描述 A message containing letters fromA-Zis being encoded to numbers using the following mapping: 'A' -> 1 'B' -> 2 ... 'Z' -> 26 Given an encoded message containing digits, determine the total number of ways to decode it. For example,Given encoded message"12", it could be decoded as"AB"(1 2) or"L"(12). The number of ways decoding"12"is 2. 思路 这题有点意思,和之前做过的一道动态规划题很相似。多了判断条件,难度稍微提高了一些。老样子,碰到动态规划,拿出dp数组,大概思路:dp[i]=dp[i-1]+dp[i-2] 代码 public class Solution { public int numDecodings(String s) { int len = s.length(); if(len==0||s.charAt(0)=='0'){ return 0; } int [] dp = new int[len+1]; //dp[i]表示s字符前i个构成的子串的解码的种数 dp[0] = 1;//这个为了后面好计算,不理解可以到后面再回来看 dp[1] = 1; for(int i=1;i<len;i++){ String num = s.substring(i-1,i+1); if(Integer.valueOf(num)<=26&&s.charAt(i-1)!='0'){ dp[i+1]=dp[i+1-2]; } if(s.charAt(i)!='0'){ dp[i+1]+=dp[i+1-1]; } } return dp[len]; } } 三、排序 题目描述 Given two sorted integer arrays A and B, merge B into A as one sorted array. Note: You may assume that A has enough space to hold additional elements from B. The number of elements initialized in A and B are m and n respectively. 思路 不能开辟新空间,考虑从后往前插入A中。 代码 public class Solution { public void merge(int A[], int m, int B[], int n) { int i = m-1; int j = n-1; int index = m+n-1; while(i>=0&&j>=0){ A[index--]=A[i]>B[j]?A[i--]:B[j--]; } while(j>=0){ A[index--]=B[j--]; } } }

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册