? ? ? 废话不多说,直接进入正题,对于最近几天刷的算法题进行总结,大部分题需要技巧,但技巧总是忘记,所以记录一下。
- 关于数组?
- 关于字符串
- 关于链表
关于数组:
1.
给定一个整数数组 nums?和一个整数目标值 target,请你在该数组中找出 和为目标值 target??的那?两个?整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9 输出:[0,1] 解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。 示例 2:
输入:nums = [3,2,4], target = 6 输出:[1,2] 示例 3:
输入:nums = [3,3], target = 6 输出:[0,1] 提示:
2 <= nums.length <= 104 -109 <= nums[i] <= 109 -109 <= target <= 109 只会存在一个有效答案
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/two-sum 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
没有太在意复杂度,基本思路是创建一个长度为2的数组存储答案,两个for循环进行遍历。不考虑复杂度比较简单。
class Solution {
public int[] twoSum(int[] nums, int target) {
int []result=new int[]{0,1};
if(nums.length==2){
return result;
}
for(int i=0;i<nums.length;i++){
for(int m=i+1;m<nums.length;m++){
if(nums[i]+nums[m]==target){
result[0]=i;
result[1]=m;
return result;
}
}
}
return result;
}
}
?
?2.盛水最多的容器
给你?n ?个非负整数?a1,a2,...,a n ,每个数代表坐标中的一个点?(i,?ai) ?。在坐标内画?n ?条垂直线,垂直线?i ?的两个端点分别为?(i,?ai) ?和?(i, 0) ?。找出其中的两条线,使得它们与?x ?轴共同构成的容器可以容纳最多的水。
输入:[1,8,6,2,5,4,8,3,7] 输出:49? 解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为?49。 示例 2:
输入:height = [1,1] 输出:1 示例 3:
输入:height = [4,3,2,1,4] 输出:16 示例 4:
输入:height = [1,2,1] 输出:2
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/container-with-most-water 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
?用双指针,索引对应数据小的一方移动,算出面积,与起初存放的进行比较看是否大于,大于的话更新,小于的话不更新。
public class Solution {
public int maxArea(int[] height) {
int l = 0, r = height.length - 1;
int ans = 0;
while (l < r) {
int area = Math.min(height[l], height[r]) * (r - l);
ans = Math.max(ans, area);
if (height[l] <= height[r]) {
++l;
}
else {
--r;
}
}
return ans;
}
}
?
3.移动0
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
示例:
输入: [0,1,0,3,12] 输出: [1,3,12,0,0] 说明:
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/move-zeroes 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
?通过做题发现,如果需要找某个特定的值,往往可以使用标记,可以用一个元素。比如定义一个fast和slow,当fast一个个遍历,遇到不是0的就放在slow里面,后面直接在后面添0就可以了。
class Solution {
public void moveZeroes(int[] nums) {
int slow=0;
int len=nums.length;
for(int fast=0;fast<len;fast++){
if(nums[fast]!=0){
nums[slow]=nums[fast];
slow++;
}
}
for(;slow<len;slow++){
nums[slow]=0;
}
}
}
4.数组拆分
给定长度为?2n?的整数数组 nums ,你的任务是将这些数分成?n 对, 例如 (a1, b1), (a2, b2), ..., (an, bn) ,使得从 1 到?n 的 min(ai, bi) 总和最大。
返回该 最大总和 。
示例 1:
输入:nums = [1,4,3,2] 输出:4 解释:所有可能的分法(忽略元素顺序)为: 1. (1, 4), (2, 3) -> min(1, 4) + min(2, 3) = 1 + 2 = 3 2. (1, 3), (2, 4) -> min(1, 3) + min(2, 4) = 1 + 2 = 3 3. (1, 2), (3, 4) -> min(1, 2) + min(3, 4) = 1 + 3 = 4 所以最大总和为 4 示例 2:
输入:nums = [6,2,6,5,1,2] 输出:9 解释:最优的分法为 (2, 1), (2, 5), (6, 6). min(2, 1) + min(2, 5) + min(6, 6) = 1 + 2 + 6 = 9
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/array-partition-i 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:在本题中需要将数组排序,在排序之后对偶数索引处的值进行计算。
class Solution {
public int arrayPairSum(int[] nums) {
Arrays.sort(nums);
int sum=0;
for(int i=0;i<nums.length;i=i+2)
{
sum=sum+nums[i];
}
return sum;
}
}
5.
给定一个已按照 升序排列??的整数数组?numbers ,请你从数组中找出两个数满足相加之和等于目标数?target 。
函数应该以长度为 2 的整数数组的形式返回这两个数的下标值。numbers 的下标 从 1 开始计数 ,所以答案数组应当满足 1 <= answer[0] < answer[1] <= numbers.length 。
你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。
? 示例 1:
输入:numbers = [2,7,11,15], target = 9 输出:[1,2] 解释:2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。 示例 2:
输入:numbers = [2,3,4], target = 6 输出:[1,3] 示例 3:
输入:numbers = [-1,0], target = -1 输出:[1,2]
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution {
public int[] twoSum(int[] numbers, int target) {
int[] res=new int[2];
int left=0,right=numbers.length-1;
while(left<right){
if(numbers[left]+numbers[right]==target){
res[0]=left+1;
res[1]=right+1;
break;
}else if(numbers[left]+numbers[right]<target){
left++;
}else{
right--;
}
}
return res;
}
}
?另附一个二分查找元素出现次数的代码
class Solution {
public int search(int[] nums, int target) {
int left =0,right = nums.length-1;
int count = 0;
while(left<right){
int mid = (left+right)/2;
if(nums[mid]>=target)
right=mid;
if(nums[mid]<target)
left = mid+1;
}
while(left<nums.length&&nums[left++]==target)
count++;
return count;
}
}
字符串:
1.最后一个单词的长度
给你一个字符串 s,由若干单词组成,单词之间用单个或多个连续的空格字符隔开。返回字符串中最后一个单词的长度。如果不存在最后一个单词,请返回 0?。
单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。
示例 1:
输入:s = "Hello World" 输出:5 示例 2:
输入:s = " " 输出:0
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/length-of-last-word 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:首先使用trim()函数,消除前后的空格,然后通过spilt分割,得到的是一个数组,直接计算数组最后一个元素的长度?。
class Solution {
public int lengthOfLastWord(String s) {
if (s == null || s.isEmpty()) {
return 0;
}
s = s.trim();
String[] strs = s.split(" ");
return strs[strs.length-1].length();
}
}
2.最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串?""。
示例 1:
输入:strs = ["flower","flow","flight"] 输出:"fl" 示例 2:
输入:strs = ["dog","racecar","car"] 输出:"" 解释:输入不存在公共前缀。
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/longest-common-prefix 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:首先取出第一个字符,然后用第一个开始做循环,与后面的字符串进行比较indexOf(String str),来判断是否存在在str字符串,如果不存在就将str的长度减1,通过subString实现
class Solution {
public String longestCommonPrefix(String[] strs) {
int i=1;
String str=strs[0];
int length=strs.length;
for(;i<length;i++){
while(strs[i].indexOf(str)!=0){
str=str.substring(0,str.length()-1);
}
}
return str;
}
}
?s.chars().sum()可以计算出对应的ascll码之和
class Solution {
public char findTheDifference(String s, String t) {
int a=s.chars().sum();
int b=t.chars().sum();
int c=b-a;
return (char)c;
}
}
给你一个链表的头节点?head ?和一个整数?val ?,请你删除链表中所有满足?Node.val == val ?的节点,并返回?新的头节点?。
输入:head = [1,2,6,3,4,5,6], val = 6 输出:[1,2,3,4,5] 示例 2:
输入:head = [], val = 1 输出:[] 示例 3:
输入:head = [7,7,7,7], val = 7 输出:[]
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/remove-linked-list-elements 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。?
思路:插入一个头结点,将其指向head,当找到val时就进行删除,找不到就看下一个元素,但是返回值是dummyhead.next,是为了解决头节点删除的问题。
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode dummyhead=new ListNode(0);
dummyhead.next=head;
ListNode prev=dummyhead;
while(prev.next!=null){
if(prev.next.val==val){
prev.next=prev.next.next;
}
else
{
prev=prev.next;
}
}
return dummyhead.next;
}
}
?
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeElements(ListNode head, int val) {
while(head!=null &&head.val==val){
head=head.next;
}
ListNode cur=head;
while(cur!=null)
{
if(cur.next!=null&&cur.next.val==val){
cur.next=cur.next.next;
}
else{
cur=cur.next;
}
}
return head;
}
}
给定一个链表,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
如果链表中存在环,则返回 true 。 否则,返回 false 。
进阶:
你能用 O(1)(即,常量)内存解决此问题吗?
示例 1:
?
输入:head = [3,2,0,-4], pos = 1 输出:true 解释:链表中有一个环,其尾部连接到第二个节点。 示例?2:
?
输入:head = [1,2], pos = 0 输出:true 解释:链表中有一个环,其尾部连接到第一个节点。 示例 3:
?
输入:head = [1], pos = -1 输出:false 解释:链表中没有环。
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/linked-list-cycle 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
?
思路:环形链表,定义一个fast和slow,fast一次走两格,slow一次走一格,如果是环就一定会相遇,记得要判断head是否为空。
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public boolean hasCycle(ListNode head) {
if(head==null){
return false;
}
ListNode slow=head;
ListNode fast=head.next;
while(fast!=null&&fast.next!=null)
{
if(fast==slow){
return true;
}
fast=fast.next.next;
slow=slow.next;
}
return false;
}
}
?
3.反转链表
给你单链表的头节点?head ?,请你反转链表,并返回反转后的链表。
?
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]
输入:head = [1,2]
输出:[2,1]
示例 3:
输入:head = []
输出:[]
?
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
ListNode prev=null;
ListNode cur=head;
while(cur!=null){
ListNode nextnode=cur.next;
cur.next=prev;
prev=cur;
cur=nextnode;
}
return prev;
}
}
?代码非常的巧妙。
加油加油加油
|