LeetCode编程题
LeetCode编程题1
class Solution {
public int[][] transpose(int[][] A) {
//获取传入数组的列数
int row=A[0].length;
//获取传入数组的行数
int column=A.length;
//返回数组的行数为传入数组的列数,列数为传入数组的行数
int data[][]=new int[row][column];
//判断是否为方形矩阵,为方形矩阵对称交换,否则顺序交换
if(row==column){
for(int i=0;i<row;i++){
for(int j=i;j<column;j++){
data[i][j]=A[j][i];
data[j][i]=A[i][j];
}
}
}
else{
for(int i=0;i<row;i++){
for(int j=0;j<column;j++){
data[i][j]=A[j][i];
}
}
}
return data;
}
}
class Solution {
//将输入数据去重后从1遍历判断该数是否在数组中,不在就返回该最小的数,否则返回数组的长度加1
public int firstMissingPositive(int[] nums) {
//获取数组的长度存入去重的set集合中,从1遍历判断是否存在该数组中
int len = nums.length;
Set<Integer> hashSet = new HashSet<>();
for (int num : nums) {
hashSet.add(num);
}
//不存在就返回该数,否则就返回数组的长度加1
for (int i = 1; i <= len; i++) {
if (!hashSet.contains(i))
return i;
}
return len + 1;
}
}
class Solution {
public int[] twoSum(int[] nums, int target) {
//循环数组判断数组两两相加是否等于目标数,相等返回
int len = nums.length;
int[] result = new int[2];
for (int i = 0; i < len - 1; i++) {
for (int j = i + 1; j < len; j++) {
if (nums[i] + nums[j] == target) {
result[0] = i;
result[1] = j;
break;
}
}
}
return result;
}
}
LeetCode编程题2
思路: 循环遍历字符串,遇到?就获取?两边的字符,如果?位于第一位则?左边的字符为"",同理若?在最后右边的字符也为"",然后在从字符a遍历只要遍历的字符不等于?左右两边的字符就替换该字符,遍历完后输出。
class Solution {
public String modifyString(String s) {
char[] ch = s.toCharArray();
for (int i = 0; i < ch.length; i++) {
if (ch[i] == '?') {
//前面一个字符 如果当前是第0个的话 字符就为‘ ’
char ahead = i == 0 ? ' ' : ch[i - 1];
//后面一个字符 如果当前是最后一个的话 字符就为‘ ’
char behind = i == ch.length - 1 ? ' ' : ch[i + 1];
//从a开始比较 如果等于前面或者后面的话 就+1
char temp = 'a';
while (temp == ahead || temp == behind ) {
temp++;
}
//找到目标字符后 做替换
ch[i] = temp;
}
}
return new String(ch);
}
}
思路: 5的二进制为101,它的反码是111与101异或得到的,所以找到比N大的每位都为1的数,与N进行异或就可以得到该数的反码。
class Solution {
public int bitwiseComplement(int N) {
int num = 1;
while(num < N){
//每次左移一位,加一保证每位都为1
num = (num << 1) + 1;
}
//异或得该数的反码
return N ^ num;
}
}
思路: 循环判断首尾字符是否相等,遇到非数字和字母就跳过该字符,如果其中有一个字符不相等就不是回文字符串返回false,结束程序,相等的话首字符递增,尾字符递减,继续循环判断。
class Solution {
public boolean isPalindrome(String s) {
String str = s.toUpperCase();
int l=0,r=str.length()-1;
while(l < r) {
// 判断当期是否为数字和字母,不是的话,就跳过该字符l向右移动
while (l < r && !Character.isLetterOrDigit(str.charAt(l))) {
l++;
}
// 判断当期是否为数字和字母,不是的话,就跳过该字符r向左移动
while (l < r && !Character.isLetterOrDigit(str.charAt(r))) {
r--;
}
// 判断l和r所指向的字符是否相等,不相等,则不是回文串,相等就继续判断下一个字符
if (str.charAt(l) != str.charAt(r)) {
return false;
}
l++;
r--;
}
//循环完没结果则代表该字符串是回文
return true;
}
}
LeetCode编程题3
思路: 循环该数每次获取该数的最后一位,并累乘十,反序,之后去除最后一位,在继续循环直到为0为止。
class Solution {
public int reverse(int x) {
int result = 0;
while(x != 0) {
//循环判断改值是否溢出
if(result < -214748364 || result > 214748364 ) {
return 0;
}
//反序计算该数
result = result * 10 + x % 10;
x /= 10;
}
return result;
}
}
思路: 首先判断该数是否小于0,小于0直接返回false结束程序,否则就按上一题的思路求该数的反序,在与正序数比较,相等返回true,否则返回false.
class Solution {
public boolean isPalindrome(int x) {
//小于0直接返回false,不回文
if(x < 0) {
return false;
}
//大于0求反序判断与正序是否相等,相等返回true,不相等返回false
int reverseNum = 0,temp = x;
while(temp != 0) {
reverseNum = reverseNum * 10 + temp % 10;
temp /= 10;
}
return x==reverseNum ? true : false;
}
}
思路: (参考)
- 罗马数字由 I,V,X,L,C,D,M 构成;
- 当小值在大值的左边,则减小值,如 IV=5-1=4;
- 当小值在大值的右边,则加小值,如 VI=5+1=6;
- 由上可知,右值永远为正,因此最后一位必然为正。
一言蔽之,把一个小值放在大值的左边,就是做减法,否则为加法。
在代码实现上,可以往后看多一位,对比当前位与后一位的大小关系,从而确定当前位是加还是减法。当没有下一位时,做加法即可。
也可保留当前位的值,当遍历到下一位的时,对比保留值与遍历位的大小关系,再确定保留值为加还是减。最后一位做加法即可。
import java.util.*;
class Solution {
public int romanToInt(String s) {
int sum = 0;
int preNum = getValue(s.charAt(0));
for(int i = 1;i < s.length(); i ++) {
int num = getValue(s.charAt(i));
if(preNum < num) {
sum -= preNum;
} else {
sum += preNum;
}
preNum = num;
}
sum += preNum;
return sum;
}
private int getValue(char ch) {
switch(ch) {
case 'I': return 1;
case 'V': return 5;
case 'X': return 10;
case 'L': return 50;
case 'C': return 100;
case 'D': return 500;
case 'M': return 1000;
default: return 0;
}
}
}
LeetCode编程题4
思路: 取出数组数组中的第一个字符串,将这个字符串与剩下的所有字符串比较,如与第二个字符串比较,获取这两个字符串中较短的长度,作为一个循环的条件,每次循环比较两个字符串的字符是否相等,一直找到最长前缀,后在截取字符串返回,在重复同样的步骤,即可。
class Solution {
public String longestCommonPrefix(String[] strs) {
if(strs == null || strs.length == 0){
return "";
}
String prefix = strs[0];
int count = strs.length;
for(int i=1; i<count; i++){
//比较两字符串的字符是否有相同的前缀
prefix = longestPrefix(prefix,strs[i]);
if(prefix.length() == 0){
break;
}
}
return prefix;
}
public String longestPrefix(String str1,String str2){
int min = Math.min(str1.length(),str2.length());
int index = 0;
while(index < min && str1.charAt(index)==str2.charAt(index)){
index++;
}
return str1.substring(0,index);
}
}
思路: 首先判断该字符串是否为偶数,不为偶数返回false,否则继续判断,在定义一个栈,每次遇到左括号就入栈,遇到右括号就判断与当前栈顶的元素是否相等,相等就出栈,判断下一个,否则就返回false结束程序运行,直到栈为空则括号全匹配。
class Solution {
public boolean isValid(String s) {
//字符串为奇数返回false
if(s.length()%2==0){
Stack<Character> stack=new Stack<>();
//左括号入栈,右括号出栈判断
for(int i=0;i<s.length();i++){
char c=s.charAt(i);
if(c=='('||c=='['||c=='{'){
stack.push(c);
}
else if(c==')'){
if(!stack.isEmpty()&&stack.peek()=='('){stack.pop();}
else{return false;}
}
else if(c=='}'){
if(!stack.isEmpty()&&stack.peek()=='{'){stack.pop();}
else{return false;}
}
else{
if(!stack.isEmpty()&&stack.peek()=='['){stack.pop();}
else{return false;}
}
}
return stack.isEmpty();
}
return false;
}
}
思路:
我们可以如下递归地定义两个链表里的 merge 操作(忽略边界情况,比如空链表等):
list1[0]+merge(list1[1:],list2) list1[0]<list2[0]
list2[0]+merge(list1,list2[1:]) otherwise
也就是说,两个链表头部值较小的一个节点与剩下元素的 merge 操作结果合并。
如果 l1 或者 l2 一开始就是空链表 ,那么没有任何操作需要合并,所以我们只需要返回非空链表。否则,我们要判断 l1 和 l2 哪一个链表的头节点的值更小,然后递归地决定下一个添加到结果里的节点。如果两个链表有一个为空,递归结束。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if(l1 == null) {
return l2;
}
if(l2 == null) {
return l1;
}
if(l1.val < l2.val) {
l1.next = mergeTwoLists(l1.next, l2);
return l1;
} else {
l2.next = mergeTwoLists(l1, l2.next);
return l2;
}
}
}
LeetCode编程题5
思路: 数组完成排序后,我们可以放置两个指针 i 和 j,其中 i是慢指针,而 j 是快指针。只要 nums[i] = nums[j],我们就增加 j以跳过重复项。
当我们遇到 nums[j] != nums[i]时,跳过重复项的运行已经结束,因此我们必须把它(nums[i])的值复制到 nums[i + 1]。然后递增 i,接着我们将再次重复相同的过程,直到 j 到达数组的末尾为止。
class Solution {
public int removeDuplicates(int[] nums) {
if(nums.length == 0) return 0;
//定义双指针,i为慢指针,j为快指针,只要两个数字不相等就将j对应的值赋值给i
int i = 0;
for(int j=1; j < nums.length; j++) {
if(nums[i] != nums[j]){
nums[++i] = nums[j];
}
}
return i+1;
}
}
思路: 与上一题相同
class Solution {
public int removeElement(int[] nums, int val) {
//定义一个双指针
int i = 0;
for(int j =0; j<nums.length; j++){
if(nums[j] != val){
nums[i++] = nums[j];
}
}
return i;
}
}
**思路:**沿着字符换逐步移动滑动窗口,将窗口内的子串与 needle 字符串比较。
class Solution {
public int strStr(String haystack, String needle) {
int l = haystack.length(), n = needle.length();
//每次截取比较是否与needle相等,相等就返回下标
for(int i =0; i< l - n + 1; i++){
if(haystack.substring(i,i + n).equals(needle)){
return i;
}
}
return -1;
}
}
LeetCode编程题6(1)
思路: 二分查找
class Solution {
public int searchInsert(int[] nums, int target) {
//定义左右指针实现二分查找,每次拿左右指针的中间值比较
int index = nums.length,l = 0,r = nums.length -1;
while(l <= r) {
int mid = (l + r) / 2;
if(nums[mid] < target) {
l = mid + 1;
}else{
r = mid -1;
}
}
return l;
}
}
思路: 递归加指针
class Solution {
//层层递进想到递归
public String countAndSay(int n) {
if(n==1) //递归结束条件
return "1";
String str = countAndSay(n-1); //上一轮的输出是是下一轮的输入
StringBuffer ans = new StringBuffer(); //存放当前轮答案
int len = str.length();
int start = 0; //记录开始下标
for(int i=1;i<len+1;i++){
if(i==len) //最后一个元素单独处理
ans.append(i - start).append(str.charAt(start));
else if(str.charAt(i) != str.charAt(start)){ //元素改变触发函数
ans.append(i - start).append(str.charAt(start));
start = i; //更新起始下标
}
}
return ans.toString();
}
}
思路:
class Solution {
public int maxSubArray(int[] nums) {
int ans = nums[0];
int sum = 0;
for(int num: nums) {
if(sum > 0) {
sum += num;
} else {
sum = num;
}
ans = Math.max(ans, sum);
}
return ans;
}
}
LeetCode编程题7(2)
思路: 从右向左遍历,从第一个不是空格的字符开始计数,一旦开始计数,再遇到空格就结束了
class Solution {
//从右向左遍历,从第一个不是空格的字符开始计数,一旦开始计数,再遇到空格就结束了
public int lengthOfLastWord(String s) {
if(s == null || s.length() == 0){
return 0;
}
int count = 0;
for(int i=s.length() - 1; i>=0; i--){
if(s.charAt(i) == ' '){
if(count == 0) continue;
break;
}
count++;
}
return count;
}
}
class Solution {
public String addBinary(String a, String b) {
int alength = a.length(), blength = b.length();
while (alength > blength)//补齐
{
b = '0' + b;
blength++;
}
while (alength < blength)
{
a = '0' + a;
alength++;
}
int carry = 0;
StringBuilder str = new StringBuilder();
for(int i=a.length() - 1; i>=0; i--){
int num = (a.charAt(i) - '0') + (b.charAt(i) - '0') + carry;
carry = num / 2;
str.append(num % 2);
}
if(carry == 1){
str.append("1");
return str.reverse().toString();
}
return str.reverse().toString();
}
}
**思路:**二分查找
class Solution {
public int mySqrt(int x) {
// 注意:针对特殊测试用例,例如 2147395599
// 要把搜索的范围设置成长整型
// 为了照顾到 0 把左边界设置为 0
// 为了照顾到 1 把右边界设置为 x / 2 + 1
long left = 0,right = (x / 2) +1;
while(left < right){
long mid = (left + right +1) / 2;
if(mid * mid > x){
right = mid-1;
}else{
left = mid;
}
}
return (int)left;
}
}
LeetCode编程题8(3)
LeetCode编程题9(3.13)
思路:
我们用 f(x) 表示爬到第 x 级台阶的方案数,考虑最后一步可能跨了一级台阶,也可能跨了两级台阶,所以我们可以列出如下式子:
f(x) = f(x - 1) + f(x - 2)
class Solution {
public: int climbStairs(int n) {
//初始化p,q为0,r为1
int p = 0,q = 0,r = 1;
//循环带入公式计算
for(int i=1; i<=n;i++){
p = q;
q = r;
r = p + q;
}
return r;
}
};
思路:遍历链表,判断当前和下一个值是否为空,为空就直接返回,不为空就继续判断当前节点的值和下一个节点的值是否相等,相等就将当前节点的指向,指向下一个节点的下一个,不相等的换就替换到下一个节点,继续遍历。
class Solution {
public ListNode deleteDuplicates(ListNode head) {
ListNode cur = head;
//判断当前节点和下一个节点是否为空
while(cur != null && cur.next != null) {
//判断当前是与下一个值是否相等相等就更换节点的指向,并清空下一个节点的指向
if(cur.val == cur.next.val){
ListNode node = cur.next;
cur.next = node.next;
node.next = null;
}else{
cur = cur.next;
}
}
return head;
}
}
思路:
定义三个指针,从两个数组的后面开始比较赋值
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
//定义三个指针,从后面开始比较
int p1 = m - 1,p2 = n- 1,p = m + n - 1;
//结束条件为p2<0
while(p2 >= 0) {
if(p1 >= 0 && nums1[p1] > nums2[p2]){
nums1[p--] = nums1[p1--];
}else{
nums1[p--] = nums2[p2--];
}
}
}
}