diff --git a/src/main/java/array/HIndex.java b/src/main/java/array/HIndex.java new file mode 100644 index 0000000..3cf95c0 --- /dev/null +++ b/src/main/java/array/HIndex.java @@ -0,0 +1,30 @@ +package array; + +import java.util.Arrays; + +/** + * 题目: 274. H 指数 (hIndex) + * 描述:给你一个整数数组 citations ,其中 citations[i] 表示研究者的第 i 篇论文被引用的次数。计算并返回该研究者的 h 指数。 + * 根据维基百科上 h 指数的定义:h 代表“高引用次数” ,一名科研人员的 h 指数 是指他(她)至少发表了 h 篇论文,并且 至少 有 h 篇论文被引用次数大于等于 h 。如果 h 有多种可能的值,h 指数 是其中最大的那个。 + * + * 示例 1: + 输入:citations = [3,0,6,1,5] + 输出:3 + 解释:给定数组表示研究者总共有 5 篇论文,每篇论文相应的被引用了 3, 0, 6, 1, 5 次。 + 由于研究者有 3 篇论文每篇 至少 被引用了 3 次,其余两篇论文每篇被引用 不多于 3 次,所以她的 h 指数是 3。 + + * 链接:https://leetcode.cn/problems/h-index/ + */ +public class HIndex { + //根据 H 指数的定义,如果当前 H 指数为 h 并且在遍历过程中找到当前值 citations[i]>h,则说明我们找到了一篇被引用了至少 h+1 次的论文, + //所以将现有的 h 值加 1。继续遍历直到 h 无法继续增大。最后返回 h 作为最终答案。 + public int hIndex(int[] citations) { + Arrays.sort(citations); + int h = 0, i = citations.length - 1; + while (i >= 0 && citations[i] > h) { + h++; + i--; + } + return h; + } +} diff --git a/src/main/java/array/IntToRoman.java b/src/main/java/array/IntToRoman.java new file mode 100644 index 0000000..0324f9c --- /dev/null +++ b/src/main/java/array/IntToRoman.java @@ -0,0 +1,53 @@ +package array; + +import java.util.*; + +/** + * 题目: 12. 整数转罗马数字 (intToRoman) + * 描述:罗马数字是通过添加从最高到最低的小数位值的转换而形成的。将小数位值转换为罗马数字有以下规则: + * 符号 值 + * I 1 + * V 5 + * X 10 + * L 50 + * C 100 + * D 500 + * M 1000 + * 如果该值不是以 4 或 9 开头,请选择可以从输入中减去的最大值的符号,将该符号附加到结果,减去其值,然后将其余部分转换为罗马数字。 + * 如果该值以 4 或 9 开头,使用 减法形式,表示从以下符号中减去一个符号,例如 4 是 5 (V) 减 1 (I): IV ,9 是 10 (X) 减 1 (I):IX。仅使用以下减法形式:4 (IV),9 (IX),40 (XL),90 (XC),400 (CD) 和 900 (CM)。 + * 只有 10 的次方(I, X, C, M)最多可以连续附加 3 次以代表 10 的倍数。你不能多次附加 5 (V),50 (L) 或 500 (D)。如果需要将符号附加4次,请使用 减法形式。 + * 给定一个整数,将其转换为罗马数字。 + * + * 示例 1: + 输入:num = 3749 + 输出: "MMMDCCXLIX" + + 解释: + 3000 = MMM 由于 1000 (M) + 1000 (M) + 1000 (M) + 700 = DCC 由于 500 (D) + 100 (C) + 100 (C) + 40 = XL 由于 50 (L) 减 10 (X) + 9 = IX 由于 10 (X) 减 1 (I) + 注意:49 不是 50 (L) 减 1 (I) 因为转换是基于小数位 + + * 链接:https://leetcode.cn/problems/remove-duplicates-from-sorted-array/ + */ +public class IntToRoman { + int[] values = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; + String[] symbols = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}; + + public String intToRoman(int num) { + StringBuffer roman = new StringBuffer(); + for (int i = 0; i < values.length; ++i) { + int value = values[i]; + String symbol = symbols[i]; + while (num >= value) { + num -= value; + roman.append(symbol); + } + if (num == 0) { + break; + } + } + return roman.toString(); + } +} diff --git a/src/main/java/array/LengthOfLastWord.java b/src/main/java/array/LengthOfLastWord.java new file mode 100644 index 0000000..9425791 --- /dev/null +++ b/src/main/java/array/LengthOfLastWord.java @@ -0,0 +1,45 @@ +package array; +/** + * 题目: 58. 最后一个单词的长度 (lengthOfLastWord) + * 描述:给你一个字符串 s,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。 + * + * 单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。 + * + * 示例 1: + 输入:s = "Hello World" + 输出:5 + 解释:最后一个单词是“World”,长度为 5。 + + * 链接:https://leetcode.cn/problems/length-of-last-word/ + */ +public class LengthOfLastWord { + public int lengthOfLastWord(String s) { + int total=s.length(); + int begin=-1,end=total; + for (int i = total-1; i >=0.; i--) { + char cur=s.charAt(i); + if(end==total&&cur==' ') { + } + else if(end == total) end=i; + else { + if (cur == ' ') { + begin = i; + break; + } + } + } + return end-begin; + } + public int lengthOfLastWord2(String s) { + int index = s.length() - 1; + while (s.charAt(index) == ' ') { + index--; + } + int wordLength = 0; + while (index >= 0 && s.charAt(index) != ' ') { + wordLength++; + index--; + } + return wordLength; + } +} diff --git a/src/main/java/array/LongestCommonPrefix.java b/src/main/java/array/LongestCommonPrefix.java new file mode 100644 index 0000000..ba4cd25 --- /dev/null +++ b/src/main/java/array/LongestCommonPrefix.java @@ -0,0 +1,32 @@ +package array; + +/** + * 题目: 14. 最长公共前缀 (longestCommonPrefix) + * 描述:编写一个函数来查找字符串数组中的最长公共前缀。 + * 如果不存在公共前缀,返回空字符串 ""。 + + * + * 示例 1: + 输入:strs = ["flower","flow","flight"] + 输出:"fl" + + * 链接:https://leetcode.cn/problems/longest-common-prefix/ + */ +public class LongestCommonPrefix { + public String longestCommonPrefix(String[] strs) { + if (strs == null || strs.length == 0) { + return ""; + } + int length = strs[0].length(); + int count = strs.length; + for (int i = 0; i < length; i++) { + char c = strs[0].charAt(i); + for (int j = 1; j < count; j++) { + if (i == strs[j].length() || strs[j].charAt(i) != c) { + return strs[0].substring(0, i); + } + } + } + return strs[0]; + } +} diff --git a/src/main/java/array/Merge1.java b/src/main/java/array/Merge1.java new file mode 100644 index 0000000..c72594f --- /dev/null +++ b/src/main/java/array/Merge1.java @@ -0,0 +1,40 @@ +package array; + +/** + * 题目: 88. 合并两个有序数组 (merge) + * 描述:给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。 + * 请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。 + * 注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。 + + * 示例 1: + 输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3 + 输出:[1,2,2,3,5,6] + 解释:需要合并 [1,2,3] 和 [2,5,6] 。 + 合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。 + + * 链接:https://leetcode.cn/problems/merge-sorted-array/ + */ +public class Merge1 { + public void merge(int[] nums1, int m, int[] nums2, int n) { + int[]temp=new int[m+n]; + int i=0,j=0,k=0; + while (i= 0) System.arraycopy(temp, 0, nums1, 0, m + n); + } +} diff --git a/src/main/java/array/RandomizedSet.java b/src/main/java/array/RandomizedSet.java new file mode 100644 index 0000000..086e0a9 --- /dev/null +++ b/src/main/java/array/RandomizedSet.java @@ -0,0 +1,71 @@ +package array; + +import java.util.*; + +/** + * 题目: 380. O(1) 时间插入、删除和获取随机元素 (RandomizedSet) + * 描述:实现RandomizedSet 类: + * RandomizedSet() 初始化 RandomizedSet 对象 + * bool insert(int val) 当元素 val 不存在时,向集合中插入该项,并返回 true ;否则,返回 false 。 + * bool remove(int val) 当元素 val 存在时,从集合中移除该项,并返回 true ;否则,返回 false 。 + * int getRandom() 随机返回现有集合中的一项(测试用例保证调用此方法时集合中至少存在一个元素)。每个元素应该有 相同的概率 被返回。 + * 你必须实现类的所有函数,并满足每个函数的 平均 时间复杂度为 O(1) 。 * + * + * 示例 1: + 输入 + ["RandomizedSet", "insert", "remove", "insert", "getRandom", "remove", "insert", "getRandom"] + [[], [1], [2], [2], [], [1], [2], []] + 输出 + [null, true, false, true, 2, true, false, 2] + + 解释 + RandomizedSet randomizedSet = new RandomizedSet(); + randomizedSet.insert(1); // 向集合中插入 1 。返回 true 表示 1 被成功地插入。 + randomizedSet.remove(2); // 返回 false ,表示集合中不存在 2 。 + randomizedSet.insert(2); // 向集合中插入 2 。返回 true 。集合现在包含 [1,2] 。 + randomizedSet.getRandom(); // getRandom 应随机返回 1 或 2 。 + randomizedSet.remove(1); // 从集合中移除 1 ,返回 true 。集合现在包含 [2] 。 + randomizedSet.insert(2); // 2 已在集合中,所以返回 false 。 + randomizedSet.getRandom(); // 由于 2 是集合中唯一的数字,getRandom 总是返回 2 。 + + * 链接:https://leetcode.cn/problems/insert-delete-getrandom-o1/ + */ +class RandomizedSet { + List nums; + Map indices; + Random random; + + public RandomizedSet() { + nums = new ArrayList(); + indices = new HashMap(); + random = new Random(); + } + + public boolean insert(int val) { + if (indices.containsKey(val)) { + return false; + } + int index = nums.size(); + nums.add(val); + indices.put(val, index); + return true; + } + + public boolean remove(int val) { + if (!indices.containsKey(val)) { + return false; + } + int index = indices.get(val); + int last = nums.get(nums.size() - 1); + nums.set(index, last); + indices.put(last, index); + nums.remove(nums.size() - 1); + indices.remove(val); + return true; + } + + public int getRandom() { + int randomIndex = random.nextInt(nums.size()); + return nums.get(randomIndex); + } +} diff --git a/src/main/java/array/RemoveDuplicates.java b/src/main/java/array/RemoveDuplicates.java new file mode 100644 index 0000000..9995df2 --- /dev/null +++ b/src/main/java/array/RemoveDuplicates.java @@ -0,0 +1,73 @@ +package array; +/** + * 题目: 26. 删除有序数组中的重复项 (removeDuplicates) + * 描述:给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。 + * 考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过: + * 更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。 + * 返回 k 。 + * + * 示例 1: + 输入:nums = [1,1,2] + 输出:2, nums = [1,2,_] + 解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。 + + * 链接:https://leetcode.cn/problems/remove-duplicates-from-sorted-array/ + */ +public class RemoveDuplicates { + //很啰嗦 + public int removeDuplicates2(int[] nums) { + int pre=0,deleted=0,start=0,invalid=Integer.MIN_VALUE; + for (int i = 1; i < nums.length; i++) { + if(nums[i]==nums[pre]) { + nums[i] = invalid; + deleted++; + } + else + pre=i; + } + for (int i = 1; i < nums.length-deleted; i++) { + if(nums[i]==invalid){ + int j; + if(start==0) + j=i+1; + else + j=start; + while (j i; j--) { + if(nums[j]!=-1) { + nums[i] = nums[j]; + nums[j]=-1; + break; + } + } + } + } + return n-chosen; + } + //双指针 + public int removeElement(int[] nums, int val) { + int i = 0, j = nums.length - 1; + while (i <= j) { + if (nums[i] == val) { + // 把尾部的元素换到 i 位置 + nums[i] = nums[j]; + // 尾部换下来的这个位置,无论是不是 val,都算处理过了 + j--; + } else { + // nums[i] 本身就不是 val,保留,继续往前 + i++; + } + } + // i 最终停在第一个“应该被移除”的位置, + // 也就是有 i 个非 val 元素 + return i; + } +} diff --git a/src/main/java/array/RomanToInt.java b/src/main/java/array/RomanToInt.java new file mode 100644 index 0000000..9e97dbb --- /dev/null +++ b/src/main/java/array/RomanToInt.java @@ -0,0 +1,60 @@ +package array; + +import java.util.HashMap; +import java.util.Map; + +/** + * 题目: 13. 罗马数字转整数 (romanToInt) + * 描述:罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。 + * 字符 数值 + * I 1 + * V 5 + * X 10 + * L 50 + * C 100 + * D 500 + * M 1000 + * 例如, 罗马数字 2 写做 II ,即为两个并列的 1 。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。 + * + * 通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况: + * + * I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。 + * X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。 + * C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。 + * 给定一个罗马数字,将其转换成整数。 + * + * 示例 1: + 输入: s = "III" + 输出: 3 + + 示例 5: + 输入: s = "MCMXCIV" + 输出: 1994 + 解释: M = 1000, CM = 900, XC = 90, IV = 4. + * 链接:https://leetcode.cn/problems/roman-to-integer/ + */ +public class RomanToInt { + Map symbolValues = new HashMap() {{ + put('I', 1); + put('V', 5); + put('X', 10); + put('L', 50); + put('C', 100); + put('D', 500); + put('M', 1000); + }}; + //左边的数比右边的小,就减法 + public int romanToInt(String s) { + int ans = 0; + int n = s.length(); + for (int i = 0; i < n; ++i) { + int value = symbolValues.get(s.charAt(i)); + if (i < n - 1 && value < symbolValues.get(s.charAt(i + 1))) { + ans -= value; + } else { + ans += value; + } + } + return ans; + } +} diff --git a/src/test/java/array/Merge1Test.java b/src/test/java/array/Merge1Test.java new file mode 100644 index 0000000..5cb21c1 --- /dev/null +++ b/src/test/java/array/Merge1Test.java @@ -0,0 +1,20 @@ +package array; + +import org.junit.Test; + +import java.util.Arrays; + +import static org.junit.Assert.*; + +public class Merge1Test { + + @Test + public void merge() { + int[] nums1 = {1,2,3,0,0,0}; + int m = 3,n=3; + int[] nums2 = {2,5,6}; + Merge1 solution = new Merge1(); + solution.merge(nums1,m,nums2,n); + System.out.println(Arrays.toString(nums1)); + } +} \ No newline at end of file diff --git a/src/test/java/array/RemoveDuplicatesTest.java b/src/test/java/array/RemoveDuplicatesTest.java new file mode 100644 index 0000000..79678f5 --- /dev/null +++ b/src/test/java/array/RemoveDuplicatesTest.java @@ -0,0 +1,19 @@ +package array; + +import org.junit.Test; + +import java.util.Arrays; + +import static org.junit.Assert.*; + +public class RemoveDuplicatesTest { + + @Test + public void removeDuplicates() { + RemoveDuplicates solution = new RemoveDuplicates(); + int[] nums = {-3,-1,0,0,0,3,3}; + int res=solution.removeDuplicates(nums); + System.out.println(res); + System.out.println(Arrays.toString(nums)); + } +} \ No newline at end of file diff --git a/src/test/java/array/RemoveElementTest.java b/src/test/java/array/RemoveElementTest.java new file mode 100644 index 0000000..d94dbe5 --- /dev/null +++ b/src/test/java/array/RemoveElementTest.java @@ -0,0 +1,16 @@ +package array; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class RemoveElementTest { + + @Test + public void removeElement() { + int[]nums={3,2,2,3}; + int val=3; + RemoveElement solution = new RemoveElement(); + solution.removeElement(nums,val); + } +} \ No newline at end of file