34. 在排序数组中查找元素的第一个和最后一个位置的思路的菜鸟总结
原题链接:https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/description/
题目描述:
给定一个按照升序排列的整数数组 nums
,和一个目标值 target
。找出给定目标值在数组中的开始位置和结束位置。
你的算法时间复杂度必须是 O(log n) 级别。
如果数组中不存在目标值,返回 [-1, -1]
。
思路:
原本以为只有两组数据测试,没有更多过难的数据测试,放松了警惕,两组数据如下:
示例 1:输入: nums = [5,7,7,8,8,10]
, target = 8 输出: [3,4]
示例 2:输入: nums = [5,7,7,8,8,10]
, target = 6 输出: [-1,-1]
对应代码只有:
for(int i=0;i
但是随着提交错误的产生,我越发知道自己的错误在哪:
首先,我没有考虑数组为零的情况,而且审题不清,题目要求是不存在目标数值则返回【-1,-1】,我却擅自返回了【0】
if(nums.size()==0) return a;
再者,我没有考虑到【1】,1的数据情况,此时应该返回【0,0】,代码如下:
if(nums.size()==1){
if(nums[0]==target) {
a[0]=a[1]=0;
return a;
最后还有一点,我没有在if(nums.size()==1) 分支语句下判断与目标值不同的情况,下面是改正后的分支语句:
else if(nums.size()==1){
if(nums[0]==target) {
a[0]=a[1]=0;
return a;
}
else return a;
}
最后考虑,其实可以使用switch语句来做这个题目,这样可以减少代码量。
源代码:
class Solution {
public:
vector searchRange(vector& nums, int target) {
int k=0;
vectora(2,-1);
if(nums.size()==0) return a;
else if(nums.size()==1){
if(nums[0]==target) {
a[0]=a[1]=0;
return a;
}
else return a;
}
else{
for(int i=0;i
27. 移除元素的简单思路与26删除数组的重复项的简单思路
27原题链接:https://leetcode-cn.com/problems/remove-element/description/
26原题链接:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/description/
27题目描述:
给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
26题目描述:
给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
分析:需要把握的点在原地修改元素和数组的长度,降低难度的点是不需要考虑新长度后面的元素。、
思路:
使用 O(1) 额外空间的条件下完成,则最好利用循环语句从数组顶部往数组底部靠拢,这样更容易来确定数组的长度,另外还需设置多余的变量来确定删除的元素个数,我这里用k来确定删除的个数。如下:
第一个和第二个循环语句:
for(int i=nums.size()-1;i>=0;i--)
for(int j=i;j
27判断数组中与寻找的变量相同,则k加一:
if(nums[i]==val) {
k++;
26判断重复项,则k加一:
if(nums[i]==nums[i-1]){
k++;
27源代码如下:
class Solution {
public:
int removeElement(vector& nums, int val) {
int k=0;
for(int i=nums.size()-1;i>=0;i--){
if(nums[i]==val) {
k++;
for(int j=i;j
26源代码如下:
class Solution {
public:
int removeDuplicates(vector& nums) {
int k=0;
for(int i=nums.size()-1;i>0;i--){
if(nums[i]==nums[i-1]){
k++;
for(int j=i;j<=nums.size()-k;j++){
nums[j-1]=nums[j];
}
}
}
return nums.size()-k;
}
};
5. 最长回文子串的简单思路
原题链接:https://leetcode-cn.com/problems/longest-palindromic-substring/description/
题目描述:
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为1000。
源代码:
class Solution {
public:
string longestPalindrome(string s) {
if(s.empty()) return s;
string res;
for(int i=0;ires.size()) res=t;
t=Palindrome(s,i,i+1);
if(t.size()>res.size()) res=t;
}
return res;
}
string Palindrome(string &s1,int l,int r){
while(l>=0&&r
思路:
考虑奇偶,设置两个判断语句。在另一个函数体中判断是否回文并返回长度,另外考虑到特殊情况。
利用到一个函数
return s1.substr(l+1, r-l-1);
复制指定长度的字符串。
3. 无重复字符的最长子串的Java方法
题目链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/description/
题目描述:
给定一个字符串,找出不含有重复字符的最长子串的长度。
错误的c++源代码:
1.
class Solution {
public:
int first,i,j;
int lengthOfLongestSubstring(string s) {
if(s.empty()) return 0;
if(s.length()==1) return 1;
for(i=0;i0) break;
}
if(t==0){
int k=y-x;
if(longest
2.
class Solution {
public:
int first,i,j;
int lengthOfLongestSubstring(string s) {
if(s.empty()) return 0;
if(s.length()==1) return 1;
for(i=0;i
总结:
自己忙了一天,还是没什么好结果,最接近正确答案是下图:
真的是崩溃,不过在这里面的错误也让我惊醒:
1.利用好循环语句,尤其是遍历类的循环,加上条件判断语句后更加要注重遍历循环语句。
2.善于利用bool类型,不要再另外一个函数体类return。
关于Java的学习:
public class Solution {
public int lengthOfLongestSubstring(String s) {
int n = s.length();
Set set = new HashSet<>();
int ans = 0, i = 0, j = 0;
while (i < n && j < n) {
// try to extend the range [i, j]
if (!set.contains(s.charAt(j))){
set.add(s.charAt(j++));
ans = Math.max(ans, j - i);
}
else {
set.remove(s.charAt(i++));
}
}
return ans;
}
}
该代码是参考:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/
我觉得很重要的一些知识点:
1.一些妙用的函数:
HashSet
Set set = new HashSet<>()
set.contains()
set.add()
set.remove()
Math.max(ans, j - i);
2.要善于利用不同语言间的优势,虽然现在没学Java,但是自己事先尝到了有一些语言的对一些题目的针对性很强,以后要多多注意。
9. 回文数的简单思路
原题链接:https://leetcode-cn.com/problems/palindrome-number/description/
题目描述:判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
进阶:
你能不将整数转为字符串来解决这个问题吗?
源代码:
class Solution {
public:
bool isPalindrome(int x) {
if(x<0||(x%10==0&&x!=0))
return false;
int temp=0;
while(x>temp){
temp=temp*10+x%10;
x/=10;
}
return temp==x||temp/10==x;
}
};
思路:
这种题目事先曾做过,此时再做算是温故知新,循环语句中X/=10这个语句没注意浪费了一些时间,看了一下阅读解答里面的解题思想,不用完全转换成数,只要转换一半即可,缩短了时间,虽然时间复杂度还不懂,但接触多了,想必会有些感悟
题目比较简单想到的方法是可以将数字直接转换成字符串,详情可以看https://blog.csdn.net/michaelhan3/article/details/75667066/
这种数字转换的方法也能想到,只是不能调用系统的函数,比较麻烦些。
4. 两个排序数组的中位数的简单思路
原题链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/description/
题目描述:
给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 。
请找出这两个有序数组的中位数。要求算法的时间复杂度为 O(log (m+n)) 。
你可以假设 nums1 和 nums2 均不为空。
源代码:
class Solution {
public:
double findMedianSortedArrays(vector& nums1, vector& nums2) {
vectora(nums1.size()+nums2.size(),NULL);
for(int i=0;i
思路:
把两个有序数组暴力组合在一起,进行排序后简单地进行寻找中位数。
1.自己不知道时间、空间复杂度的意思。
2.这个题目原本看到过,但是自己因为排序的麻烦不想去做,看到了sort()的用法,觉得可以尝试,但我觉得时间复杂度应该超过了
3.注意第二个数组赋值到总数组的时候
for(int j=nums1.size();j
4.另设的数组可以有自己的size()。
5.个人认为读代码对我很重要,感觉自己已经晚了很多,但是这种愧疚感弥补不了我读代码不懂得烦躁感,加油吧。
1. 两数之和的简单想法
题目链接:https://leetcode-cn.com/problems/two-sum/description/
原题描述:
给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。
你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。
源代码:
class Solution {
public:
vector twoSum(vector& nums, int target) {
vectora(2,0);
for(int i=0;i=0||nums[i])
for(int j=i+1;j
简单思路:
原本思考可以有先确定第一个加数再确定第二个加数的方法,不过我的考虑只停留在了正数方面,结果数据告诉我负数的情况就很纳闷,看到提示后用了暴力解答的方法,时间复杂度较高。
20. 有效的括号的简单想法
题目链接:
https://leetcode-cn.com/problems/valid-parentheses/description/
题目描述:
给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串,判断字符串是否有效。
有效字符串需满足:
注意空字符串可被认为是有效字符串。
思路:
原本是想先判断括号的数量是否契合,然后利用替换的方法来进行,但太麻烦最后选择放弃(主要还是懒),于是参考了一下别人的代码,发现栈的思想非常重要,简直是算这种题目的利器。
栈的应用:
stack cs;
cs.push(c);
cs.empty();
cs.top();
cs.pop();
注意一下细节,不要怕代码长度太长,主要是有思路能简化就好。
源代码:
class Solution {
public:
bool isValid(string s) {
stack cs;
char c;
int i=0;
while (i
41. 缺失的第一个正数的简单思路
题目链接:
https://leetcode-cn.com/problems/first-missing-positive/description/
题目描述:
给定一个未排序的整数数组,找出其中没有出现的最小的正整数。
思路:
一开始以为比较简单,没有把负数去掉的情况考虑进去,结果靠一次次数据把我敲醒。
后来整体的思路是:先选择排序,再考虑正整数的数据,考虑正整数数据没有和只有一个的情况,再考虑最小整数出现在正整数中间位置的情况,最后考虑最小整数比最大的数组整数都大的情况,情况考虑的比较多,得考虑到比较刁钻得数据。
选择排序:
int k,f,m,n=0;
if(nums.size()==0) return 1;
for(int i=0;inums[j]) k=j;
f=nums[k];
nums[k]=nums[i];
nums[i]=f;
}
考虑正整数在数组中的位置,如果都是正整数则重置为零:
for(;n0) {
n++;
break;
}
}
if(nums[0]>=0) n=0;
最后是考虑一个和多个排序好的正整数的情况:
f(nums.size()-n==1) {
if(nums[n]==1) return 2;
else return 1;
}
if(nums[n]>1) return 1;
for(m=n;m1) return nums[m]+1;
return nums[m-1]+1;
}
源代码:
class Solution {
public:
int firstMissingPositive(vector& nums) {
int k,f,m,n=0;
if(nums.size()==0) return 1;
for(int i=0;inums[j]) k=j;
f=nums[k];
nums[k]=nums[i];
nums[i]=f;
}
for(;n0) {
n++;
break;
}
}
if(nums[0]>=0) n=0;
if(nums.size()-n==1) {
if(nums[n]==1) return 2;
else return 1;
}
if(nums[n]>1) return 1;
for(m=n;m1) return nums[m]+1;
return nums[m-1]+1;
}
};
28. 实现strStr()的简单思路
原题目的链接:https://leetcode-cn.com/problems/implement-strstr/description/
题目描述:
给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。
细节:
当 needle
是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。
对于本题而言,当 needle
是空字符串时我们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。
想法:
首先,应该把特殊情况用if语句率先解决:
if(haystack.empty() && needle.empty()) return 0;
if(haystack.empty()) return -1;
if(needle.empty()) return 0;
if(haystack.size()
然后考虑怎么能让检索更为简便且快捷,排除之前的状况,考虑到 needle的长度一定会小于额度长度,我们可以利用双重循环和两者之间的差值长度来简化运行效率:
for(int i=0;i
双重循环的优势在基本的几个排序算法(冒泡排序、选择排序等)中显露无疑,在这里利用双重循环适合检索和确认needle和haystack重复部分
以下是源代码:
class Solution {
public:
int strStr(string haystack, string needle) {
if(haystack.empty() && needle.empty()) return 0;
if(haystack.empty()) return -1;
if(needle.empty()) return 0;
if(haystack.size()
总结: 自我感觉要多阅读优秀代码,多考虑题目的边界问题,掌握一些基本的技能。