博主是从简单开始做
-
Reverse Integer(反转数字)
Integer.MIN_VALUE,Integer.MAX_VALUE,表示int的最大和最小范围,使用long型防止溢出。
- Palindrome Numb(回文数)
回文数是反着和正着都相同的数,采用恢复一半的数字来判断是否为回文数,列如1221,恢复后半段1221的21为12,与前半段进行比较,如果相同则为回文数,当我们将数字除以10,并将倒数乘以10,当原始数字小于倒数时,这意味着我们已经处理了一半数字的数字,当数字长为奇数时,把恢复数再除以10,奇数中间可以不做比较
额外补充:str.reverse()字符串反转
int i = Integer.parseInt(str);String转int
String转int
String s = String.valueOf(i); String s = Integer.toString(i) int转String
int转String
- Roman to Integer(罗马数字转换为整型)
-
class Solution { public int romanToInt(String s) { int []nums=new int[s.length()]; for(int i=0;i<s.length();i++){ if(s.charAt(i)=='I'||s.charAt(i)=='i') nums[i]=1; if(s.charAt(i)=='V'||s.charAt(i)=='v') nums[i]=5; if(s.charAt(i)=='X'||s.charAt(i)=='x') nums[i]=10; if(s.charAt(i)=='L'||s.charAt(i)=='l') nums[i]=50; if(s.charAt(i)=='C'||s.charAt(i)=='c') nums[i]=100; if(s.charAt(i)=='D'||s.charAt(i)=='d') nums[i]=500; if(s.charAt(i)=='M'||s.charAt(i)=='m') nums[i]=1000; } int sum=0; for(int i=0;i<s.length()-1;i++){ if(nums[i]<nums[i+1]) sum=sum-nums[i]; else sum=sum+nums[i]; } return sum+nums[s.length()-1]; } public static void main(String[] args) { // TODO 自动生成的方法存根 Solution w=new Solution(); System.out.println(w.romanToInt("V")); } }
- 新建一个s.length()的数组nums[]来保存每个罗马数字对应的整型数字,通过charAT方法获得s中的每个字母。
- Longest Common Prefix 最长的通用前缀
public class WW {
public String longestCommonPrefix(String[] strs) {
if(strs.length==0)
return "0";
String p=strs[0];
for(int i=1;i<strs.length;i++)
while(strs[i].indexOf(p)!=0)
{
p=p.substring(0, p.length()-1);
if(p.isEmpty())
return "";
}
return p;
}
public static void main(String[] args) {
// TODO 自动生成的方法存根
WW w=new WW();
String []strs={"abc","abcde","ab"};
System.out.println(w.longestCommonPrefix(strs));
}
}
- strs[i].indexOf(p),通过indexof方法判断strs[i]中是否有p,如果有则返回0,如果没有则返回-1,进去while函数,通过substring方法裁剪p,裁剪后再通过indexof方法与strs[i]进行判断。如果裁剪到0还是没有返回0,则返回“ ”说明没有相同的前缀。
- Valid Parentheses
public class WW { public boolean isValid(String s) { Stack<Character> stack = new Stack<>(); for (int i = 0; i < s.length(); i++) { switch (s.charAt(i)) { case '(': stack.push('('); break; case '{': stack.push('{'); break; case '[': stack.push('['); break; case ')': if (stack.size() == 0 || stack.pop() != '(') return false; break; case '}': if (stack.size() == 0 || stack.pop() != '{') return false; break; case ']': if (stack.size() == 0 || stack.pop() != '[') return false; break; } } return stack.isEmpty(); } public static void main(String[] args) { // TODO 自动生成的方法存根 WW w=new WW(); System.out.println(w.isValid("")); } }
- 创建一个stack,通过switch把({[把push进栈中,然后让)}]与栈顶pop后进行比较,如果不相等,返回false,同时注意栈的长度。最后判断栈是否为空。
- 合并两个有序的链表
-
private class Node{ private int data;//每个节点的数据 private Node next;//每个节点指向下一个节点的连接 public Node(int data){ this.data = data; } } public Node mix(Node l,Node l2){ if(l==null){ return l2; }else if(l2==null){ return l; } Node l3=null; if(l.data<=l2.data){ l3=l; l3.next=mix(l.next,l2); }else{ l3=l2; l3.next=mix(l,l2.next); } return l3; }
- 采用递归的算法,l与l2数据比较,如果l小则把该结点赋给l3,然后才有递归,比较l1的下一个数据与l2当前的数据比较谁大谁小
l3.next=mix(l.next,l2);
删除排序数组中的重复项
因为题目说删除重复下,所以想到的是用hashset的无序性,用HashSet来保存num数组,来把那些重复项删除,在eclipse上能够运行,但移到LeetCode就无法通过了,原因 一直也搞不懂
public int Remove(int []num){
/*HashSet<Integer> list=new HashSet<>();
for(int i=0;i<num.length;i++){
list.add(num[i]);
}
int len=list.size();
System.out.println("len: "+len);
Iterator<Integer>it=list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}*/
官方的解答是用了双指针,当num[i]!=num[j]时,i++,同时把num[j]赋值给num]i],覆盖重复项,最后返回i+1即数组的长度
if(num==null)
return 0;
int i=0;
for(int j=1;j<num.length;j++){
if(num[j]!=num[i]){
i++;
num[i]=num[j];
}
}
return i+1;
移除元素
移除元素的方法移除数组中重复项的方法相同
public void remove(int nums[],int num){
int i=0;
for(int j=0;j<nums.length;j++){
if(nums[j]!=num){
nums[i]=nums[j];
i++;
}
}
for(int w=0;w<i;w++){
System.out.println(nums[w]);
}
}
public static void main(String[] args) {
// TODO 自动生成的方法存根
Test27 t=new Test27();
int nums[]={3,2,2,2,3};
t.remove(nums, 3);
}
实现strSTR
使用字符串中的indexOf方法即可
public void strStr(String h,String n){
if(n==null){
System.out.println(0);
}
int num=h.indexOf(n);
System.out.println(num);
}
public static void main(String[] args) {
// TODO 自动生成的方法存根
Test28 t=new Test28();
String h="aaaaaa";
String n="bba";
t.strStr(h, n);
}
搜索插入位置
这个方法很暴力,效率低,看代码都能看懂,看了别人的才知道还有个二分查找法,唉,数据结构太差了
public int find(int[] nums,int num){
int temp=0;
if(nums.length==1){
for(int i=0;i<nums.length ;i++){
if(nums[i]<num){
temp=i+1;
}else{
temp=i;
}
}
}else{
for(int i=0;i<nums.length-1;i++){
if(nums[i]==num){
temp=i;
break;
}
else if(nums[i]<num&&num<=nums[i+1]){
temp=i+1;
break;
}else if(num>nums[nums.length-1]){
temp=nums.length;
}else if(num<nums[i]){
temp=0;
}
}
}
return temp;
}
public static void main(String[] args) {
// TODO 自动生成的方法存根
Test35 t=new Test35();
int[]nums={1,2,4,6,7,9,11};
System.out.println(t.find(nums, 7));
}
二分查找法
int L=0;
int R=nums.length-1;
while(L<=R){
int mid=L+(R-L)/2;
if(nums[mid]==num)
return mid;
else if(nums[mid]>num){
R=mid-1;
}else{
L=mid+1;
}
}
return L;
报数
public String CountAndSay(int n){
String str="1";
String result="";
int sum=1;
if(n==1){
return str;
}
if(n==2){
str="11";
return str;
}
str="11";
for(int i=2;i<n;i++){
for(int j=0;j<str.length();j++){
if(j!=str.length()-1&&str.charAt(j)==str.charAt(j+1)){
sum++;
continue;
}else if(j==str.length()-1&&str.charAt(j)==str.charAt(j-1)){
result=result+String.valueOf(sum)+str.charAt(j);
sum=1;
}else{
result=result+String.valueOf(sum)+str.charAt(j);
sum=1;
}
}
str=result;
result="";
}
return str;
- 最大子序和
这道题一开始想错了方向,想了半天都没解决,最后才明白其实只需要数组每项加起来,负数不加就可以了
public int maxSubArray(int num[]){
int max[]=new int[num.length];
int maxx=num[0];
max[0]=maxx;
for(int i=1;i<num.length;i++){
max[i]=max[i-1]>0?max[i-1]+num[i]:num[i];
maxx=Math.max(max[i],maxx);
}
return maxx;
}
最后一个单词的长度
用split把带有空格的字符串分割成数组,然后取数组的最后一个转换成char数组,最后算出char数组的长度
还要判断字符串是否有单词还是只有空格
public int lengthOfLastWord(String str){
char[]ch=null;
String[]strr=str.split(" ");
if(str==" "||str==""||strr.length==0){
return 0;
}else{
ch=strr[strr.length-1].toCharArray();
}
return ch.length;
加一
用了个很暴力的方法,但在LeetCode通过不了。。先把数组转换成数字加一,然后再转换成数组,为了任意精度,选用了大数值
/*StringBuffer sb=new StringBuffer();
for(int i=0;i<num.length;i++){
sb.append(num[i]);
}
String str=sb.toString();
BigInteger big=new BigInteger(str);
BigInteger big2=new BigInteger("1");
str=String.valueOf(big.add(big2));
num=new int[str.length()];
for(int i=0;i<str.length();i++){
num[i]=Integer.parseInt(str.substring(i, i+1));
}
return num;*/
下面这个方法LeetCode可以通过
for(int i=num.length-1;i>=0;i--){
if(num[i]==9){
num[i]=0;
}else{
num[i]++;
return num;
}
}
int[]nums=new int[num.length+1];
nums[0]=1;
return nums;
x的平方根
public int mySqrt(int x){
int num=(int) Math.sqrt(x);
return num;
}
爬楼梯
运用递归来解决这个问题,也可以找出规律用循环,爬n步楼梯,可以想象成是在n-1层爬了一节楼梯,也可以是在n-2层爬了两节楼梯,以此来递归算出有多少种方法(这道题一开始没想到用递归,想找规律,结果算错了,规律一直没找到,最后上网查了才发现递归如此好用)
public int climbStairs(int n){
if(n==1)
return 1;
if(n==2)
return 2;
int nums[]=new int[n+1];
nums[1]=1;
nums[2]=2;
climb(nums,n);
return nums[n];
}
private void climb(int[]nums, int n) {
// TODO 自动生成的方法存根
int a=n-1;
int b=n-2;
if(a>2&&nums[a]==0)
climb(nums,a);
if(b>2&&nums[b]==0)
climb(nums,b);
nums[n]=nums[a]+nums[b];
}
删除排序列表中重复的元素
简单的链表删除就可以实现,但是要注意空链表的条件,通过刷题发现我对数据结构的掌握很不牢固
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode deleteDuplicates(ListNode n) {
if(n==null||n.next==null)
return n;
ListNode node=n;
ListNode node2=n.next;
while(node2!=null){
if(node.val==node2.val){
node.next=node2.next;
node2=node2.next;
}else{
node=node.next;
node2=node2.next;
}
}
return n;
}
}
合并两个有序数组
先用copyOf把数组一的长度扩大到m+n,然后数组一和数组二从最后的数开始比较(因为是有序的,所有最后的数最大),大的数放在扩大后的数组一的最后一位,一下代码在eclipse能够通过,但在LeetCode就不能通过了,也不知道为什么。
public void merge(int[] nums1, int m, int[] nums2, int n){
int temp= m+n;
nums1=Arrays.copyOf(nums1, temp);
--temp;
--m;
--n;
while(m>=0&&n>=0){
nums1[temp--]=nums1[m]>nums2[n]?nums1[m--]:nums2[n--];
}
while(n>=0){
nums1[temp--]=nums2[n--];
}
for (int i : nums1) {
System.out.print(i+" ");
}
下面的代码在LeetCode就能够通过。。。
public void merge(int[] nums1, int m, int[] nums2, int n){
int temp= m+n-1;
/*nums1=Arrays.copyOf(nums1, temp);
--temp;*/
--m;
--n;
while(m>=0&&n>=0){
nums1[temp--]=nums1[m]>nums2[n]?nums1[m--]:nums2[n--];
}
while(n>=0){
nums1[temp--]=nums2[n--];
}
for (int i : nums1) {
System.out.print(i+" ");
}
翻转数组
public void rotate(int[] nums, int k){
int length=nums.length;
k=k%length;//当K大于数组长度时,相当翻转成原来的数组,取余是为了得出翻转成原来的数组后又翻转的次数
if(length==1){
return;
}
if(k==0&&k==length){
return;
}
Filp(nums,0,length-k-1);//翻转k位之前的数字
Filp(nums,length-k,length-1);//翻转k位之后的数字
Filp(nums,0,length-1);//翻转整个数组
for (int i : nums) {
System.out.print(" "+i);
}
System.out.println(" ");
}
private void Filp(int[] nums, int i, int j) {
// TODO 自动生成的方法存根
int temp;
while(i<j&&i>=0){
temp=nums[i];
nums[i]=nums[j];
nums[j]=temp;
i++;
j--;
}
第二种方法,很简单但是在面对超大数组时会超时,因为移动数组很费时间
public void rotate(int[] nums, int k) {
while(k>0){
int temp=nums[nums.length-1];
for(int i=nums.length-1;i>0;i--){
nums[i]=nums[i-1];
}
nums[0]=temp;
k--;
}
for (int i : nums) {
System.out.print(" "+i);
}
System.out.println(" ");
}
只出现一次的数字
用两层循环记录每个数字出现的次数,然后存在map里面,最后返回键值为一的value即可
HashMap<Integer,Integer>map=new HashMap<>();
int count=1;
for(int i=0;i<nums.length;i++){
count=1;
for(int j=0;j<nums.length;j++){
if(i==j)
continue;
if(nums[i]==nums[j]){
count++;
}
}
map.put(count,nums[i]);
}
return map.get(1);
上面的方法可以通过但是太耗时间,花了700多ms 在网上了解到java的异或运算符,利用异或运算符的特性可以很快的完成这道题
int result=0;
for(int i=0;i<nums.length;i++){
result^=nums[i];
}
return result;
相同数字异或为0,不同数字数字异或为1,
两个数组的交集II
public int[] intersect(int[] nums1, int[] nums2) {
ArrayList<Integer> list = new ArrayList<>();
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int i = 0; i < nums1.length; i++) {
Integer value = map.get(nums1[i]);
map.put(nums1[i], (value == null ? 0 : value) + 1);
}
for (int i = 0; i < nums2.length; i++) {
if (map.containsKey(nums2[i]) && map.get(nums2[i]) != 0) {
list.add(nums2[i]);
map.put(nums2[i], map.get(nums2[i]) - 1);
}
}
int[] nums3 = new int[list.size()];
int i = 0;
for (Integer e : list)
nums3[i++] = e;
return nums3;
}
移动零
采用两个指针,都指向数组的最后一位,一个指针向前查找零的位置,找到零后,把数组向前移动,然后把第二个指针的位置改为零。
public void moveZeroes(int[] nums){
int one=nums.length-1;
int two=nums.length-1;
while(two>=0){
if(nums[two]==0){
int count=one-two;
for(int i=0;i<count;i++){
nums[two+i]=nums[two+i+1];
}
nums[one]=0;
one--;
}
two--;
}
for (int i : nums) {
System.out.print(" "+i);
}
}
有效的数独
只需要判断行有没有重复,列有没有重复,3×3方块有没有重复即
public boolean isValidSudoku(String[][] board) {
HashSet<String> rowSet=new HashSet<>();
HashSet<String> colSet=new HashSet<>();
for(int i=0;i<9;i++){
rowSet.clear();
colSet.clear();
for(int j=0;j<9;j++){
if(i%3==0&&j%3==0){//检查3×3有没有重复数字
if(!CheckBlock(board, i, j))
return false;
}
if(board[i][j]!="."){//检查行有没有重复数字
if(rowSet.contains(board[i][j]))
return false;
rowSet.add(board[i][j]);
}
if(board[j][i]!="."){//检查列有没有重复数字
if(colSet.contains(board[j][i]))
return false;
colSet.add(board[j][i]);
}
}
}
return true;
}
public boolean CheckBlock(String[][]board,int row,int col){
HashSet<String> blockSet=new HashSet<>();
for(int i=row;i<row+3;i++){
for(int j=col;j<col+3;j++){
if(board[i][j]!="."){
if(blockSet.contains(board[i][j]))
return false;
blockSet.add(board[i][j]);
}
}
}
return true;
}