给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
题解
方法接收参数为一个int数组 和一个目标值
创建一个Map :key:数组元素 value:数组下标
循环数组 ,判断map中是否有一个key等于 目标值减去当前循环数组元素
如果有 就结束方法 返回key对应的下标 和当前循环到的下标
如果循环走完 还没有匹配 返回 -1, -1
public static int[] twoSum2(int[] nums, int target){
if (nums == null || nums.length < 2){
return new int []{-1, -1};
}
int [] res = new int[]{-1, -1};
HashMap map = new HashMap<>();
for (int i = 0; i < nums.length; i++){
// 判断集合中有没有一个键 等于 目标值减去当前值
if (map.containsKey(target - nums[i])){
res[0] = map.get(target - nums[i]); // 和当前值对应的那个值的下标
res[1] = i; // 当前值下标
break;
}
map.put(nums[i],i); // 把当前值 和下标加入到 集合中
}
return res;
}
给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
题解
定义一个res 为long型 为了防止反转后的越界
res每次*10 表示每次整体数字在最后加一位0
在加上 传过来的值%10表示把传过来的值最后一位加上去,再把传过来的值/10表示消除最后一位
当res超出int最大值 或小于int最小值的时候 返回0
否则把反转后的结果返回
public static int reverse2(int x) {
long res = 0;
while (x != 0) {
res = res * 10 + x % 10; // 当前结果*10表示增加一位数 各位为0 x % 10 最传入值的各位
x /= 10; // x值减少一位
if (res > Integer.MAX_VALUE || res < Integer.MIN_VALUE) return 0;
}
return (int)res;
}
判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
题解
不断的把最后一位取出来附加到临时变量(temp)的个位
当temp大于传入参数(x)的时候 循环结束
返回结果 : temp == x || x == temp / 10 ;
temp / 10 表示如果传入参数为奇数 需要去除中位数在比较
public static boolean isPalindrome(int x) {
// 小于0的数 不是回文数
// 最后一位为0的数不是回文数 如果为了使该数为回文数 只能是0
if (x < 0 || (x % 10 == 0 && x != 0)) {
return false;
}
int temp = 0;
while (x > temp) {
// 为了把数反过来 例:x=121 temp=0
// 0*10 +121 % 10=1 1*10 + 12%10 = 12
temp = temp * 10 + x % 10;
// x=12 x=1
x /= 10;
}
// 当数字长度为奇数时 可以通过temp / 10 去除中位数
// 例: 12321 在进入while循环后 x = 12 temp = 123
// 中位的数字不影响回文,所以可以将它去除
return temp == x || x == temp / 10;
}
如果理解不了 可以定一个零时变量(palind)存储传入的参数
再定义一个参数用来存储反转后的值(rev)
rev * 10 (增加一位) + x %10 取换入参数的最后一位
再把传入参数 / 10 去掉最后一位
返回 : 当palind == rev表示是回文数
public static boolean isPalindrome2(int x) {
if (x < 0 || x != 0 && x % 10 == 0) return false;
int palind = x; // 先把 传进来的 x 值赋给一个新的变量
int rev = 0; // 用于接收 翻转后的值
while (x > 0) { // 反转
rev = rev * 10 + x % 10;
x /= 10;
}
return palind == rev; // 判断反转后的值和 原来的值是否一致
}
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。
字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:
I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。
题解
这里是有一个规律的,如果左边的数字小于右边的数字 = 右减左
首先定义一个方法,用于吧字符转成对应的数字
循环判断,如果循环到的这个数字 大于 前一个数 上面所说的规则成立
res += 当前值 - 2 * 前一个值
前两个是因为 前一个数再上一次循环的时候就已经加进去了,如果只是减一个那只能起到抵消的效果,没有起到减的效果
public static int romanToInt2(String s) {
if (s == null || s.length() == 0) return 0;
int res = toNumber(s.charAt(0));
for (int i = 1; i < s.length(); i++){
if (toNumber(s.charAt(i)) > toNumber(s.charAt(i - 1))){
// res += toNumber(s.charAt(i)) 表示的是把前面的数加上当前数
// 如果后面不减两个前一个数的话 就只是把前一次数抵消掉 没有起到减的效果
res += toNumber(s.charAt(i)) - 2 * toNumber(s.charAt(i - 1));
}else {
res += toNumber(s.charAt(i));
}
}
return res;
}
public static int toNumber(char c){
int res = 0;
switch (c) {
case 'I' : return 1;
case 'V' : return 2;
case 'X' : return 10;
case 'L' : return 50;
case 'C' : return 100;
case 'D' : return 500;
case 'M' : return 1000;
}
return res;
}
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 “”。
题解
定义一个临时变量(prefix)存放公共前缀
循环数组长度,内嵌套循环,条件:如果当前元素不是以prefix开头,就把prefix截取掉最后一位,再接着循环,找出他们两的公共前缀,其后每个元素同理接着操作
如果prefix为空了 表示没有公共的前缀 直接返回“”
public static String longestCommonPrefix(String[] strs) {
if (strs.length == 0) {
return "";
}
String prefix = strs[0];
for (int i = 1; i < strs.length; i++){
// 如果获取第一次出现的位置 为0的话 代表从开头开始都一样 但是第一个子串只有那么长 然后要取的是公共的最长 ,
// 所以 如果第二个字符串比第一个长 最长公共串最多也只能是第一个字符串
while (strs[i].indexOf(prefix) != 0) {// 如果两个字符串的 前缀 一样的话 表示 当前的prefix是他们的公共前缀
// 更新相同的字符串前缀 每次把最后一个字符截取掉 在进行比较,
prefix = prefix.substring(0, prefix.length()-1);
if (prefix.isEmpty()) {// 如果为null了 表示他们没有公共前缀
return "";
}
}
}
return prefix;
}
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
题解
使用栈存储结构 先进后出
循环字符串
判断字符为(、[、{的时候 把对应的)、]、}存入栈
当循环到右括号的时候 从栈顶取出一个元素进行比较 如果不匹配 或栈已经为空 直接返回false
最后 如果栈中还剩余元素 也表示不匹配 返回false
public static boolean isValid2(String s) {
if (s == null || s.length() == 0) return true;
Stack stack = new Stack<>();
for (Character ch : s.toCharArray()){ // 编译所有字符
// 如果是左括号就添加进 栈
if (ch == '('){
stack.push(')');
}else if(ch == '['){
stack.push(']');
}else if(ch == '{'){
stack.push('}');
}else{
// 如果是右括号 就根栈顶元素比较 只要不匹配就直接返回false
if (stack.isEmpty() || stack.pop() != ch) {
return false;
}
}
}
// 如果全都匹配了 就没有剩余元素了 返回true
return stack.isEmpty(); // 如果最后还有剩余的元素,返回false
}
将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
题解
初始化一个链表
在初始化一个链表 很第一个产生关联 用于迭代操作
循环判断 两个链表是否为空 只要其中一个为空就把剩下的值直接加到创建的链表中,如果不为空把小的值加到链表中,再更新链表中的值和用于迭代的链表
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode dummy = new ListNode(0); // 创建一个链表
ListNode cur = dummy;
while (l1 != null && l2 != null) { // 当其中一个链表的值没了就结束
if (l1.val < l2.val) {
cur.next = l1; // 把值给链表
l1 = l1.next; // 刷新到下一个值
}else{
cur.next = l2;
l2 = l2.next;
}
cur = cur.next;
}
// 哪个链表空了就把另一个链表之间接在后面
if (l1 == null) {
cur.next = l2;
}else{
cur.next = l1;
}
return dummy.next;
}
还一种递归解法 代码很简单 但是空间复杂度上升到了O(n)
public ListNode mergeTwoLists2(ListNode l1, ListNode l2) {
if (l1 == null) return l2;
if (l2 == null) return l1;
if (l1.val < l2.val) {
l1.next = mergeTwoLists2(l1.next,l2);
return l1;
}else{
l2.next = mergeTwoLists2(l1,l2.next);
return l2;
}
}
给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
题解
定义一个变量 用于存储长度(i)
从下标为1的元素开始迭代 每次跟前一个元素比较 不相等i++ 相同的情况下进入下一次循环,最后返回i + 1 因为循环从1开始 所以最后得把第一个数加回来
public int removeDuplicates(int[] nums) {
if (nums.length == 0) return 0;
int i = 0;
for (int j = i + 1; j < nums.length; j++){
if (nums[j] != nums[i]){ // 因为是一个排序数组,所以 每个不相同的数添加一个就好了 但是会忽略掉第一个
nums[++i] = nums[j]; // 第一个数组元素不变 所以使用++i
}
}
// 因为走循环的话 第一个数不会被加进去
return i + 1;
}
给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
题解
这题就太简单了吧!!
定义一个临时变量 index 用来标识新数组下标位置
循环判断,吧不等于目标值的数加入数组下标为index的位置 index++ 最后返回index
public static int removeElement(int[] nums, int val) {
if (nums == null || nums.length == 0) return 0;
int index = 0;
for (int i = 0; i < nums.length; i++){
if (val != nums[i]){ // 把每个不等于val的值从新给赋值给数组
nums[index++] = nums[i];// index用来标识 新添加元素的数组下标
}
}
return index;
}
实现 strStr() 函数。
给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1
题解
哎 !!
不多说直接上代码
方法1:
public int strStr(String haystack, String needle) {
if(needle == null || needle.equals("")) return 0;
return haystack.indexOf(needle);
}
方法2:
public int strStr2(String haystack, String needle) {
if(needle == null || needle.equals("")) return 0;
for (int i = 0; i <= haystack.length() - needle.length(); i++){
if (haystack.substring(i, i + needle.length()).equals(needle)) return i;
}
return -1;
}