the primary algorithm of leetcode
1. 数组
1.1删除重复数组中的排序项
//双指针解决
public int removeDuplicates(int[] A) {
//边界条件判断
if (A == null || A.length == 0)
return 0;
int left = 0;
for (int right = 1; right < A.length; right++)
//如果左指针和右指针指向的值一样,说明有重复的,
//这个时候,左指针不动,右指针继续往右移。如果他俩
//指向的值不一样就把右指针指向的值往前挪
if (A[left] != A[right])
A[++left] = A[right];//左指针先右移,再被赋值
return ++left;
}
1.2 买股票的最佳时期II
这里主要运用到的思想是动态规划。在以时间为序列的股票价格数组中,可进行任意的股票买入和卖出,因此买家在任意一天呈现两种状态,一个是持有股票(意味着只能进行股票的卖出或者继续持有),第二个是不持有股票(意味着可以保持不持有或者买入股票)。因此我们讲第 i 天的利润情况分成两个数组 dp[i][0],dp[i][1] 接着就可以结合前一天的状态推断出递推条件与初始边界条件,并在最终返回dp[length - 1][0](最右上角的数组,即代表最后一天卖出股票所有后最终的利润)public int maxProfit(int[] prices) {
if (prices == null || prices.length < 2)
return 0;
int length = prices.length;
int[][] dp = new int[length][2];
//初始条件
dp[0][1] = -prices[0];
dp[0][0] = 0;
for (int i = 1; i < length; i++) {
//递推公式
dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
}
//最后一天肯定是手里没有股票的时候,利润才会最大,
//只需要返回dp[length - 1][0]即可
return dp[length - 1][0];
}
1.3 旋转数组
public void rotate(int nums[], int k) {
int length = nums.length;
int temp[] = new int[length];
//把原数组值放到一个临时数组中,
for (int i = 0; i < length; i++) {
temp[i] = nums[i];
}
//然后在把临时数组的值重新放到原数组,并且往右移动k位
for (int i = 0; i < length; i++) {
nums[(i + k) % length] = temp[i];
}
}
1.4 存在重复元素(有重复即返回true,vice versa)
1.暴力法效率过低,由于返回的数据类型为布尔,所以可以在对原数组进行一定修改的基础上,进行检测。 因此第一种算法是利用Array.sort() 对数组进行排序,然后看相邻是否有相同的数值2.使用Set集合。因为已知java 的 set集合中是不可以出现重复的元素。因此创建一个set,并在添加元素时候,如果出现了重复的元素时,添加就会返回false.
public boolean containsDuplicate(int[] nums) {
Set<Integer> set = new HashSet<>();
for (int num : nums) {
//因为集合set中不能有重复的元素,如果有重复的
//元素添加,就会添加失败
if (!set.add(num))
return true;
}
return false;
}
只出现一次的数字
思路1:利用异或运算去实现。 a^a=0;自己和自己异或等于0 a^0=a;任何数字和0异或还等于他自己 a^b^c=a^c^b;异或运算具有交换律 有了这3个规律,这题就很容易解了,我们只需要把所有的数字都异或一遍,最终的结果就是我们要求的那个数字。来看下代码public int singleNumber(int nums[]) {
int result = 0;
for (int i = 0; i < nums.length; i++)
result ^= nums[i];
return result;
}
思路2:仍旧利用set集合的性质。如果添加一个元素,这个值存在则删去,因此成对出现的数值将在集合中消失。
public int singleNumber(int[] nums) {
Set<Integer> set = new HashSet<>();
for (int num : nums) {
if (!set.add(num)) {
//如果添加失败,说明这个值
//在集合Set中存在,我们要
//把他给移除掉
set.remove(num);
}
}
//最终集合Set中只有一个元素,我们直接返回
return (int) set.toArray()[0];
}
1.5 两个数组中的交集II
思路1:nums1,nums2。两个数组共同进行排序,并利用两个指针开始依次比对。 当指针所指数值不相同时,数值较小的指针++,若相同时,则两个指针均++。直至其中一方数组遍历结束为止。 public int[] intersect(int[] nums1, int[] nums2) {
// 先对两个数组进行排序
Arrays.sort(nums1);
Arrays.sort(nums2);
int i = 0;
int j = 0;
List<Integer> list = new ArrayList<>();
while (i < nums1.length && j < nums2.length) {
if (nums1[i] < nums2[j]) {
// 如果i指向的值小于j指向的值,,说明i指向
// 的值小了,i往后移一步
i++;
} else if (nums1[i] > nums2[j]) {
// 如果i指向的值大于j指向的值,说明j指向的值
// 小了,j往后移一步
j++;
} else {
// 如果i和j指向的值相同,说明这两个值是重复的,
// 把他加入到集合list中,然后i和j同时都往后移一步
list.add(nums1[i]);
i++;
j++;
}
}
//把list转化为数组
int index = 0;
int[] res = new int[list.size()];
for (int k = 0; k < list.size(); k++) {
res[index++] = list.get(k);
}
return res;
}
思路2:使用map解决。
首先遍历所有nums1中的元素,将他们存放到map中,其中key就是nums1中的元素;value就是在num1中出现的次数。
然后遍历nums2,并在map中一一进行对照,没有对应上的则进行删除,进行对照上的就留下并添加到新的数组当中,并最终返回这个数组。
public int[] intersect(int[] nums1,int[] nums2){
HashMap<Integer,Integer> map = new HashMap<>();
ArrayList<Integer> list = new ArrayList<>();
for(int i=0;i<nums1.length;i++){
map.put(nums1[i],map.getOrDefault(nums1[i],0)+1);//getOrDefault() 方法获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值
}
for(int i=0;i<nums2.length;i++){
if(map.getOrDefault(nums2[i],0)>0){
list.add(nums2[i]);
map.put(nums2[i],map.get(nums2[i])-1)
}
}
//把集合list转换为数组
int res[] = new int[list.size()];
for (int i=0;i<list.size();i++){
res[i] = list.get(i);
}
return res;
}
1.6 两数之和
这类问题一般可以直接用暴力算法直接进行暴力解决,但是占用的内存等空间会过多。因此我们会选择利用java的hashmap模块去进行解决。class Solution {
public int[] twoSum(int[] nums, int target) {
HashMap<Integer,Integer> map = new HashMap<>();
for(int i = 0;i<nums.length;i++){
if(map.get(target-nums[i])!=null){
//map.get()函数可以get到一个哈希表里面特定数值的位置索引,若未有找到该值,则返回空null
return new int[]{map.get(target-nums[i]),i};
}
map.put(nums[i],i);
}
return new int[]{0,0};
}
}
hashmap用法总结
1.7 有效的数独
请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)
public boolean isValidSudoku(char board[][]) {
int length = board.length;
//二维数组line表示的是对应的行中是否有对应的数字,比如line[0][3]
//表示的是第0行(实际上是第1行,因为数组的下标是从0开始的)是否有数字3
int line[][] = new int[length][length];
int column[][] = new int[length][length];
int cell[][] = new int[length][length];
for (int i = 0; i < length; ++i)
for (int j = 0; j < length; ++j) {
//如果还没有填数字,直接跳过
if (board[i][j] == '.')
continue;
//num是当前格子的数字
int num = board[i][j] - '0' - 1;
//k是第几个单元格,9宫格数独横着和竖着都是3个单元格
int k = i / 3 * 3 + j / 3;
//如果当前数字对应的行和列以及单元格,只要一个由数字,说明冲突了,直接返回false。
//举个例子,如果line[i][num]不等于0,说明第i(i从0开始)行有num这个数字。
if (line[i][num] != 0 || column[j][num] != 0 || cell[k][num] != 0)
return false;
//表示第i行有num这个数字,第j列有num这个数字,对应的单元格内也有num这个数字
line[i][num] = column[j][num] = cell[k][num] = 1;
}
return true;
}
参考内容:
作者:力扣 (LeetCode)
链接:https://leetcode.cn/leetbook/read/top-interview-questions-easy/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
参考链接:https://www.bilibili.com/video/BV1iT41157a7/?spm_id_from=333.337.search-card.all.click&vd_source=9b226b0c66c354e394eae99edb289b69
(作者B站:博哥的数据结构和算法)