35、搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素。
题解
循环数组 从后往前找,当匹配到第一个比目标值小的那个元素下标的时候 返回下标+1就是目标值要插入的位置,如果有正好匹配的值 直接返回下标
public int searchInsert(int[] nums, int target) {
for(int i = nums.length - 1; i >= 0; i--){
if(nums[i] == target){
return i;
}
if(nums[i] < target){
return i + 1;
}
if(i == 0){
return 0;
}
}
return -1;
}
53、最大子序和
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
题解
直接看代码注释吧,很简单的一道题
public static int maxSubArray3(int[] nums) {
/*
1 3 -5 2
res = 1 sum = 1
res = 4 sum = 4
res = 4 sum = -1
res = 4 sum = 2
*/
int res = nums[0];
int sum = nums[0];
for (int i = 1; i < nums.length; i++){
// 当前和加上当前值 都没有当前值大的话就 直接取当前值去很最大和比较
sum = Math.max(nums[i], sum + nums[i]);
res = Math.max(res, sum); // 最大和
}
return res;
}
方法二:
public static int maxSubArray(int[] nums) {
// 数组中第一个元素 也是用来存储最大值的
int res = nums[0];
int sum = 0;
for (int num : nums) {// 遍历所有数组
if (sum > 0) sum += num;
else sum = num;// 如果当和等于负数的时候 直接不要之前的和了 把当前值给sum
res = Math.max(res, sum);// 更新最大的和 把res和 当前最大整数和相比 如果全都是负数的话就都直接进入这里比较
}
return res;
}
58、最后一个单词的长度
给定一个仅包含大小写字母和空格 ’ ’ 的字符串,返回其最后一个单词的长度。
如果不存在最后一个单词,请返回 0 。
说明:一个单词是指由字母组成,但不包含任何空格的字符串。
题解
到目前为止最简单的题了
方法一 :
按空格拆分 取最后一段的长度!!
public int lengthOfLastWord(String s) {
String [] strs = s.split(" +");
if(s.trim().equals("")){
return 0;
}else{
return strs[strs.length-1].length();
}
}
方法二:
去掉前后空格 后 整体长度减去最后一个空格之前的长度 lastIndexOf是从0开始 最后多减一个1
public int lengthOfLastWord2(String s) {
return s.trim().length() - s.trim().lastIndexOf(" ") - 1;
}
66、加一
给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。
最高位数字存放在数组的首位, 数组中每个元素只存储一个数字。
你可以假设除了整数 0 之外,这个整数不会以零开头。
题解
这题分为三种情况
最后一位小于9的时候 直接加1 返回
最后一位d等于9的时候 当前位数归0表示进1接着走循环 当出现第一个小于9的时候加1返回
最后一种情况 例如 9999 加1 总位数会加1 当循环走完 还没有返回, 新建一个数组 第一位为0
public int[] plusOne(int[] digits) {
if (digits == null || digits.length == 0) return digits;
for (int i = digits.length - 1; i >= 0; i--){
if (digits[i] < 9) {
digits[i]++;
return digits;
}else{
digits[i] = 0;
}
}
int[] res = new int[digits.length + 1];
res[0] = 1;
return res;
}
67、二进制求和
给定两个二进制字符串,返回他们的和(用二进制表示)。
输入为非空字符串且只包含数字 1 和 0。
题解
不断的取模 除2 最后考虑进位问题就行了
首先使用一个StringBuilder就可以防止不断的开辟新的空间
两数从后往前相加,定义一个用于记录进位的变量
最后循环走完的时候判断是否还有进位 有就把进位添加到StringBuilder中
反向输出 返回
public static String addBinary(String a, String b) {
StringBuilder sb = new StringBuilder();
int i = a.length() - 1;
int j = b.length() - 1;
int remainder = 0;
while (i >= 0 || j >= 0) {
int sum = remainder; // 上一次循环计算的进位
if (i >= 0) sum += a.charAt(i) - '0'; // 把最后每次循环的最后一位数加给sum
if (j >= 0) sum += b.charAt(j) - '0';
sb.append(sum % 2); // %2 二进制遇二进 1
remainder = sum / 2; // 如果除2 有余数 用remainder接收进位
i--; j--;
}
if (remainder != 0) { // 当循环走完 还有一个进位 就把进位添加到sb中
sb.append(remainder);
}
return sb.reverse().toString();// 反向输出
}
70、爬楼梯
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
题解
其实就是一个斐波那契数
举个例子: 假设你只差最后一步就走到第10级台阶,这时候分为两种情况,9-10或8-10走一步或两步 ,既然想要走到第10级,那最后一步必然是从8或9开始,那么如果已知0-9有X种走法,0-8有Y种走法,那么0-10就有 X + Y种走法
这个时候把问题反过来想,
当走到1级台阶的时候 只有1种走法 1
当走到2级台阶的时候有2种走法 11 2
根据上面的推断 F(n) = F(n-1) + F(n-2);
那三级台阶的走法就是 1 + 2 等于3种
四级台阶的走法就是 2 + 3 等于5种 以此类推
public int climbStairs(int n) {
if (n <= 1) return 1;
int oneStep = 1, twoStep = 1, res = 0;
for (int i = 2; i <= n; i++){
res = oneStep + twoStep;
twoStep = oneStep;
oneStep = res;
}
return res;
}
方法二 :递归解法 不推荐使用 时间复杂度近似O(2^n)
if (n <= 2) { // 如果是只有一级台阶 只有一种方式 如果有两级台阶有2种方式,11 2
return n;
}else{
return climbStairs(n -1) + climbStairs2(n - 2);
}
83、删除排序列表种的重复元素
给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。
题解
这题超简单,,,
如果当前值和它的next值相等 就让它的next直接指向 next的next
public static ListNode deleteDuplicates(ListNode head) {
if (head == null || head.next == null) return head;
ListNode temp = head;
while(temp != null && temp.next != null){
if (temp.val == temp.next.val){
temp.next = temp.next.next;
}else{
temp = temp.next;
}
}
return head;
}
88、合并两个有序数组
给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。
说明:
初始化 nums1 和 nums2 的元素数量分别为 m 和 n。
你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。
题解
因为nums1和nums2本身就是有序的,所有就可以直接从最后开始比较 谁大就取谁 然后–
最后因为是把两个数组合并到nums1 所有如果 j 小于0了 nums1剩下的不用管,如果i小于0了就把nums[j]剩下的放在数组前面
public void merge(int[] nums1, int m, int[] nums2, int n) {
int i = m - 1;
int j = n - 1;
int k = m + n - 1;
while (i >= 0 && j >= 0){
nums1[k--] = nums1[i] >= nums2[j] ? nums1[i--] : nums2[j--];
}
while (j >= 0) {
nums1[k--] = nums2[j--];
}
}
100、相同的树
给定两个二叉树,编写一个函数来检验它们是否相同。
如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
题解
当两个树都为空的时候 表示他们相等
当有一个树为空的时候 不相等
当前节点的值不相等 返回false
最后递归 把两个树的左子树比较,把两个树的右子树进行比较
public boolean isSameTree(TreeNode p, TreeNode q) {
if (p == null && q == null) return true;
if (p == null || q == null) return false;
if (p.val != q.val) return false;
return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
}
101、对称二叉树
给定一个二叉树,检查它是否是镜像对称的。
题解
思路: t1的左子树等于t2的右子树
t1的右子树 等于t2的左子树
public boolean isSymmetric(TreeNode root) {
return isMirror(root, root);
}
public boolean isMirror(TreeNode t1, TreeNode t2) {
if (t1 == null && t2 == null) return true;
if (t1 == null || t2 == null) return false;
return (t1.val == t2.val)
&& isMirror(t1.right, t2.left)
&& isMirror(t1.left, t2.right);
}