此篇文章用户记录leetcode的简单题
leetcode9给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。例如,121 是回文,而 123 不是。
分析 看到这道题目首先我想的是反证法比如121是不是一个回文数只需要把他反过来121看两数是否需要相等即可,但是发现编译报错,这是因为int类型可能会爆表,比如x = 2,147,483,646 也就是反过来一定会超出范围所以不可行,我们只需要比较一半就可以定义一个revertedNumber 当x > renvertedNumber去做比较即可 代码如下
class Solution {
public boolean isPalindrome(int x) {
if(x < 0 || (x % 10 == 0 && x != 0)){
return false;
}
int revertedNumber = 0;
while(x > revertedNumber){
revertedNumber = revertedNumber * 10 + x % 10;
x /= 10;
}
return x == revertedNumber || x == revertedNumber / 10;
}
}
LeetCode27:给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
分析 双指针法: 一个指针指向有效元素个数 另一个指针用来判断是不是要移除的数字,如果不是要移除的数字那么就把他给有效数字的指针即可,然后有效指针自增。代码如下
public int removeElement(int[] nums, int val) {
if (nums == null || nums.length == 0)
return 0;
int j = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] != val) {
nums[j] = nums[i];
j++;
}
}
return j;
}
双指针优化 如果要移除的元素恰好在数组的开头,例如序列 [1,2,3,4,5],当 val 为 1 时,我们需要把每一个元素都左移一位。注意到题目中说:「元素的顺序可以改变」。实际上我们可以直接将最后一个元素 5 移动到序列开头,取代元素 1,得到序列 [5,2,3,4][5,2,3,4],同样满足题目要求。这个优化在序列中 元素的数量较少时非常有效。此方法借鉴了leetcode官方。
class Solution {
public int removeElement(int[] nums, int val) {
int left = 0;
int right = nums.length;
while (left < right) {
if (nums[left] == val) {
nums[left] = nums[right - 1];
right--;
} else {
left++;
}
}
return left;
}
}
如果换成int right = nums.length - 1
后面if换成nums[left] = nums[right] 会正确吗?
注意题目返回的是新的长度 所以这样一定不可以
leetcode20
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
分析 用(){}[]<>的ASCII值差为1或者为2所以只需要用一个栈来存储括号,每次进来看栈顶的top-c==-1||-2(由于左括号必须以正确的顺序闭合。)就可以了代码如下
class Solution {
public boolean isValid(String s) {
if(s.length() % 2 == 1){
return false;
}
Stack<Character>stack = new Stack<Character>();
char c;
boolean a = true;
for(int i = 0; i < s.length(); i++){
c = s.charAt(i);
if(stack.empty()){
stack.push(c);
}else{
char top = stack.peek();
if(top -c == -1 || top - c == -2){
stack.pop();
}else{
stack.push(c);
}
}
}
return a == stack.isEmpty();
}
}
leetcode232
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):
实现 MyQueue 类:
void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空,返回 true ;否则,返回 false
说明:
你只能使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
进阶:
你能否实现每个操作均摊时间复杂度为 O(1) 的队列?换句话说,执行 n 个操作的总时间复杂度为 O(n) ,即使其中一个操作可能花费较长时间。
来源:力扣(LeetCode)
分析:用栈实现队列就需要一个辅助栈进队的话直接进 出队先把A的元素全移到B然后弹出B栈顶的元素即可
初始 两个栈 进队列1-6
出栈
代码如下
class MyQueue {
private Stack a;// 输入栈
private Stack b;// 输出栈
public MyQueue() {
a = new Stack<>();
b = new Stack<>();
}
public void push(int x) {
a.push(x);
}
public int pop() {
// 如果b栈为空,则将a栈全部弹出并压入b栈中,然后b.pop()
if(b.empty()){
while(!a.empty()){
b.push(a.pop());
}
}
return b.pop();
}
public int peek() {
if(b.empty()){
while(!a.empty()){
b.push(a.pop());
}
}
return b.peek();
}
public boolean empty() {
return a.empty() && b.empty();
}
}
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue obj = new MyQueue();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.peek();
* boolean param_4 = obj.empty();
*/
leetode167两数之和
给定一个已按照 升序排列 的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target 。
函数应该以长度为 2 的整数数组的形式返回这两个数的下标值。numbers 的下标 从 1 开始计数 ,所以答案数组应当满足 1 <= answer[0] < answer[1] <= numbers.length 。
你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。
方法一:双指针法
定义一个指针low等于0,一个指针high等于numbers.length-1
然后low与high对应的值相加如果小,则low++;
如果大则high–;
class Solution {
public int[] twoSum(int[] numbers, int target) {
int low = 0;
int high = numbers.length - 1;
while(low < high){
int sum = numbers[low] + numbers[high];
if(sum < target){
low++;
}else if(sum > target){
high--;
}else{
return new int[]{low + 1, high + 1};
}
}
return null;
}
}
方法二 二分查找法
定义两个指针low每次等于i+1 high等于numbers.length - 1
每次用target- nums[i]看这个值是否存在low-high的区间中
用二分法
如果小于中间值则high = mid - 1
如果大于中间值则low = mid + 1
class Solution {
public int[] twoSum(int[] numbers, int target) {
for(int i = 0; i < numbers.length; i++){
int low = i + 1;
int high = numbers.length - 1;
if(target - numbers[i] > numbers[high]){
continue;
}
if(target - numbers[i] < numbers[low]){
break;
}
while(low <= high){
int mid = (high + low)/2 + low;
if(numbers[mid] == target - numbers[i]){
return new int[]{low + 1, high + 1};
}else if (numbers[mid] > target - numbers[i]){
high = mid - 1;
}else{
low = mid + 1;
}
}
}
return new int[]{-1,-1};
}
}
leetcode905按奇偶排序数组
给定一个非负整数数组 A,返回一个数组,在该数组中, A 的所有偶数元素之后
跟着所有奇数元素你可以返回满足此条件的任何数组作为答案。
方法一:选择排序法
运用选择排序的方法遍历所有数字 遇到奇数和后面的偶数换位置
class Solution {
public int[] sortArrayByParity(int[] nums) {
for(int i = 0; i < nums.length; i++){
if(nums[i] % 2 == 1){
for(int j = i + 1; j < nums.length; j++){
if(nums[j] % 2 == 0){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
}
}
return nums;
}
}
方法二:双指针法
两个指针一前一后 看两遍是奇数还是偶数
代码如下
class Solution {
public int[] sortArrayByParity(int[] nums) {
int l = 0;
int r = nums.length - 1;
while(l < r){
if(nums[l] % 2 == 0 && nums[r] % 2 == 0){
l++;
}else if(nums[l] % 2 == 1 && nums[r] % 2 == 0){
int temp = nums[l];
nums[l] = nums[r];
nums[r] = temp;
}else if(nums[l] % 2 == 1 && nums[r] % 2 == 1){
r--;
}else{
l++;
r--;
}
}
return nums;
}
}
leetcode66
给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。
最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。
你可以假设除了整数 0 之外,这个整数不会以零开头。
方法:倒序遍历
我们需要考虑这几种情况
每次的数字加1之后应该%10 然后carry为每次的数字/10
class Solution {
public int[] plusOne(int[] digits) {
int carry = 1;
for(int i = digits.length - 1; i >= 0; i--){
int num = digits[i] + carry;
digits[i] = num % 10;
carry = num / 10;
if(carry == 0){
break;
}
}
if(carry == 1){
int[] arr = new int[digits.length + 1];
arr[0] = 1;
return arr;
}
return digits;
}
}