力扣题目
- 第一周 2021.3.11-2021.3.20
完成情况
3.12
/*
1. 两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。
**你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。**
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
*/
//new一个数组,遍历,看头+尾是否=target,有则return
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] result = new int[2];
for (int i = 0; i < nums.length; i++) {
for (int j = nums.length - 1; j > i; j--) {
if (nums[i] + nums[j] == target){
result[0] = i;
result[1] = j;
break;
}
}
}
return result;
}
}
3.13
/*
2. 两数相加
**给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。**
请你将两个数相加,并以相同形式返回一个表示和的链表。
**你可以假设除了数字 0 之外,这两个数都不会以 0 开头。**
示例 1:
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
示例 2:
输入:l1 = [0], l2 = [0]
输出:[0]
*/
/**
* Definition for singly-linked list.
*ListNode类有val属性和next属性
* 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; }
* }
*/
//ListNode是一个带有val属性和next属性的类
//他不断传入参数l1和l2直到传入的值为空
//通过对两个参数和进位的直接相加,就可的出计算的结果,最后判断进位是否还==0,否则指定下一位的值为进位值
class Solution {
public static ListNode addTwoNumbers(ListNode l1, ListNode l2) {
//创建两个ListNode类型的对象
ListNode head = null, tail = null;
int carry = 0;
//tail.next:下一位
//while直到两个链表都为空
while (l1 != null || l2 != null) {
//判断是否为空,是则 赋值 0
int n1 = l1 != null ? l1.val : 0;
int n2 = l2 != null ? l2.val : 0;
//计算链表每一位的值
int sum = n1 + n2 + carry;
//当链表头为空时,将其个位数赋值到其中(计算第一个数时用到)
if (head == null) {
head = tail = new ListNode(sum % 10);//个位数
} else {//否则则进位并赋值
tail.next = new ListNode(sum % 10);//个位数
tail = tail.next;
}
carry = sum / 10; //进位
//两个链表同时进位
if (l1 != null) {
l1 = l1.next;
}
if (l2 != null) {
l2 = l2.next;
}
}
//当while结束但是carry大于0时,说明有进位,则再进一位
if (carry > 0) {
tail.next = new ListNode(carry);
}
//返回链表
return head;
}
}
3.14
/*
3. 无重复字符的最长子串
**给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。**
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
*/
//新建一个新的集合,将不重复的字符串放入,若遍历后发现重复,则删除头,直到第一个重复元素删除掉为止
//用set集合是因为set不保存重复字符,并继承Collection接口,可提供添加删除等方法,且长度可自由变换
class Solution {
public static int lengthOfLongestSubstring(String s) {
// 哈希集合,记录每个字符是否出现过
Set<Character> occ = new HashSet<Character>();
int n = s.length();
// 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动
int rk = -1, ans = 0;
for (int i = 0; i < n; ++i) {
if (i != 0) {
// 左指针向右移动一格,移除一个字符,直到相同元素移除完为止
occ.remove(s.charAt(i - 1));
}
//通过contains()方法,循环查找是否有与occ哈希表相同的元素,有则跳过,回到if循环中删除第一个元素,无则添加元素到occ中
//循环条件,不超过字符串长度,并且没有出现occ中有的元素,若有,则跳出循环
while (rk + 1 < n && !occ.contains(s.charAt(rk + 1))) {
// 将元素添加到occ集合中
occ.add(s.charAt(rk + 1));
rk++;
}
// 判断是否为最长字符串
ans = Math.max(ans, rk - i + 1);
}
return ans;
}
}
3.15
/*
4. 寻找两个正序数组的中位数
**给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。**
示例 1:
输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2
示例 2:
输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5
*/
//以下做法条理清晰,自行解读
//利用数组,并使用System类的arraycopy方法追加数组
class Solution {
public static double findMedianSortedArrays(int[] nums1, int[] nums2) {
int targetlong = nums1.length+nums2.length;
int[] target = new int[targetlong];
int mid1;
int mid2;
double reslut = 0;
//1.判断输入的数组是否为空
//2.新建数组 target 数组追加数组
System.arraycopy(nums1,0,target,0,nums1.length);
System.arraycopy(nums2,0,target,nums1.length, nums2.length);
//3.数组排序
Arrays.sort(target);
//4.判断target数组长度是否为偶数
if (targetlong % 2 == 0){
mid1 = targetlong / 2;
mid2 = mid1 - 1;
reslut = (double) (target[mid1] + target[mid2])/2;
}else if (targetlong % 2 != 0){
mid1 = targetlong / 2;
reslut = (double)target[mid1];
}
return reslut;
}
}
3.16
/*
5. 最长回文子串
**给你一个字符串 s,找到 s 中最长的回文子串。**
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
示例 2:
输入:s = "cbbd"
输出:"bb"
*/
//通过嵌套for循环,实现对数组的每个数进行比较,同时增加条件是最长的回文子串,逻辑相对简单,但实现较为复杂。
class Solution {
public String longestPalindrome(String s) {
//1.只有一个字符串直接返回
if (s.length()<2){
return s;
}
//2.转换成数组
char[] ans = s.toCharArray();
int begin = 0;
int maxlong = 1;
//3.遍历,最后一位不需要遍历
for (int i = 0; i < ans.length-1; i++) {
for (int j = i+1; j < ans.length; j++) {
//3.1比较maxlong是否是最长的,不是则没必要比了
if (j-i+1 > maxlong && judge(ans,i,j)){
//如果传回来的是true
begin = i;//起始值
maxlong = j-i+1;//起始值到末尾的长度
}
}
}
//4.new一个数组进行输出
char[] res = new char[maxlong];
for (int i = 0; i < maxlong; i++) {
res[i] = ans[begin];
begin++;
}
return new String(res);
}
//3.1判定是否是会问子串
public boolean judge(char[] ans,int left, int right){
while (left < right){
//3.2遍历两个重复数之间是否都处于对称状态
//不是则输出false,若直到left=right都相等,则输出true
if (ans[left] != ans[right]){
return false;
}
left++;
right--;
}
return true;
}
}
3.17
/*
6. Z 字形变换
**将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。**
比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:
P A H N
A P L S I I G
Y I R
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);
示例 1:
输入:s = "PAYPALISHIRING", numRows = 3
输出:"PAHNAPLSIIGYIR"
示例 2:
输入:s = "PAYPALISHIRING", numRows = 4
输出:"PINALSIGYAHRPI"
*/
//通过判断x是否==0或者==长度-1,将每一个字符按顺序放入numRows个数组中,最后按顺序合并成字符串
//使用StringBuilder的原因:
//他是可改变字符串,通过append()、insert()、reverse()、setCharAt()、setLength()等方法可以改变这个字符串对象的字符序列
//并且速率比String快的多
class Solution {
public String convert(String s, int numRows) {
int x = 0;
int flag = 1;
//1.判断是否有字符,无则返回s
if (s.length() == 0 || s.toCharArray() == null ||numRows == 1) return s;
//2.new一个长度为numRows的类型为StringBuilder的字符数组
StringBuilder[] sb = new StringBuilder[numRows];
for (int i = 0; i < sb.length; i++) {
//3.在里面再创建一个StringBuilder类型的数组,相当于{{},{},{}}
sb[i] = new StringBuilder();
}
//4.通过判断x是否等于0或者是否=长度-1 分别存放进不一样的数组中
for (char c : s.toCharArray()) {
sb[x].append(c);
x = x+flag;
if (x == 0 || x == numRows-1){
flag = -flag;
}
}
//5.创建一个StringBuilder类型对象
StringBuilder res = new StringBuilder();
//6.将三个合并在一起
for (int i = 0; i < sb.length; i++) {
res.append(sb[i]);
}
return new String(res);
}
}
3.18
/*
7. 整数反转
**给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。**
**如果反转后整数超过 32 位的有符号整数的范围 [−2^31, 2^31 − 1] ,就返回 0。**
**假设环境不允许存储 64 位整数(有符号或无符号)。**
(本题解法忽视这个提示,当然也提供了判断[−2^31, 2^31 − 1]的方法,请自行参照)
示例 1:
输入:x = 123
输出:321
示例 2:
输入:x = -123
输出:-321
*/
//本人做法,相对长,且运行速度较慢,可自行参考答案
//重点是如何将数字反转的计算:result = (int) (yu*Math.pow(10,i-1)) + result;
class Solution {
public int reverse(int x) {
int i = 0;
long result = 0;
int yu = 0;
int reslong = 0;
if (x == 0){ return x;}
//1.判断结尾是否有0,并去掉后面的0
if (x%10 == 0){
x = x/10;
}
//2.得出把后面0除掉得结果
int number = x;
//3.计算是多少位数
while (number != 0){
number=number/10;
i++;
}
reslong = i;
//4.直接计算出结果
for (int j = 0; j < reslong; j++) {
yu = x%10;
result = (int) (yu*Math.pow(10,i-1)) + result;
x = x/10;
i--;
}
System.out.println(result);
//通过类型强制转换得出是否超过[−2^31, 2^31 − 1]范围
return (int)result == result ? (int) result : 0;
}
}
/*
**判断是否超过 2^31 − 1
(result > Integer.MAX_VALUE / 10 || (result == Integer.MAX_VALUE / 10 && (currChar - '0') > Integer.MAX_VALUE % 10))
**判断是否超过 −2^31
(result < Integer.MIN_VALUE / 10 || (result == Integer.MIN_VALUE / 10 && (currChar - '0') > -(Integer.MIN_VALUE % 10)))
*/
3.19
/*
8. 字符串转换整数 (atoi)
请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C++ 中的 atoi 函数)。
函数 myAtoi(string s) 的算法如下:
**
读入字符串并丢弃无用的前导空格
检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。
读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。
将前面步骤读入的这些数字转换为整数(即,"123" -> 123, "0032" -> 32)。如果没有读入数字,则整数为 0 。必要时更改符号(从步骤 2 开始)。
如果整数数超过 32 位有符号整数范围 [−2^31, 2^31 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −2^31 的整数应该被固定为 −231 ,大于 2^31 − 1 的整数应该被固定为 2^31 − 1
**
注意:
本题中的空白字符只包括空格字符 ' ' 。
除前导空格或数字后的其余字符串外,请勿忽略 任何其他字符。
示例 1:
输入:s = "42"
输出:42
解释:加粗的字符串为已经读入的字符,插入符号是当前读取的字符。
第 1 步:"42"(当前没有读入字符,因为没有前导空格)
^
第 2 步:"42"(当前没有读入字符,因为这里不存在 '-' 或者 '+')
^
第 3 步:"42"(读入 "42")
^
解析得到整数 42 。
由于 "42" 在范围 [-231, 231 - 1] 内,最终结果为 42 。
*/
//以下做法条理清晰,自行解读,就是简单的对字符串进行筛选,并无复杂计算
class Solution {
public int myAtoi(String s) {
int res = 0;
int index = 0; //下标
//1.转换字符串
int length = s.length();
char[] ans = s.toCharArray();
//2.统计他的前置空格' '
while (index < length && ans[index] == ' '){
index++;
}
//判断是否为空的字符串
if (index == length){
return 0;
}
//3.查看其第一个字符是+还是-
int sign = 1;
if (ans[index] == '+'){
index++;
}
else if (ans[index] == '-'){
sign = -1;
index++;
}
//4.统计后面的数
while (index < length){
char first = ans[index];
//4.1判断是否为数字,不是则直接跳出
if (first > '9' || first < '0'){
break;
}
//4.2判断是否大于2的31次方-1(符号占一位)
if (res > Integer.MAX_VALUE/10 || res == Integer.MAX_VALUE/10 && (first-'0') > Integer.MAX_VALUE%10){
return Integer.MAX_VALUE;
}
if (res < Integer.MIN_VALUE/10 || res == Integer.MIN_VALUE/10 && (first-'0') > -(Integer.MIN_VALUE%10)){
return Integer.MIN_VALUE;
}
//5.计算res等于多少
res = res*10 + sign*(first-'0');
index++;
}
return res;
}
}
3.20
/*
9. 回文数
**给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。**
**回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。例如,121 是回文,而 123 不是。
示例 1:
输入:x = 121
输出:true
示例 2:
输入:x = -121
输出:false
解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
*/
//我的思路正确,但方法较为复杂,好像有更简单的方法,可以看答案
//将x对半分成前面部分和后面部分,比较前面和后面的数字是否大小相等!
class Solution {
public boolean isPalindrome(int x) {
//1.判断是否为(负数,最后一位为0的非个位数,除了0之外,都是非回文整数)
if (x<0 || x%10 == 0 && x != 0){
return false;
}
//2.个位数则直接输出x
if (x>=0 && x<=9){
return true;
}
int number = x;
int length = 0;
//3.计算有多少位数
while (number != 0){
number = number/10;
length++;
}
//这里可以用Integer类进行包装直接得出length
//4.分成两个数,并把后面的数调转
int halflength = 0;
halflength = length/2;
//5.前面的数
int befor = (int) (x/Math.pow(10,halflength));
//6.后面的数
int behind = 0;
int number2 = x;
int halflength2 = halflength;
if (length % 2 == 0){
halflength2 = halflength-1;
}
while (halflength >= 0) {
behind = (int) ((number2 % 10) * Math.pow(10, halflength2) + behind);
number2 = number2/10;
halflength--;
halflength2--;
}
//比较前后两个数的大小是否相等
if (befor == behind){
return true;
}
return false;
}
}
-
以上为本人 “奋进的叻叻” 第一个星期的算法题目练习,每周周日会进行总结,以上代码均为自己所写,或有参考会做记录,并重新手写一遍,以加深记忆。
-
(并不是所有解答均为最有效方法,只是本人最熟悉的方法,以后会更加专注于代码效率的提升)
-
第一周练习,思路并不清晰,注释并不完善条理,将会不断提升
-
或许有错误的地方,请帮忙指出,谢谢。
-
题目以及部分解答出自力扣