- 一,初次尝试
- 1.两数之和
- 2.两数相加
- 3.整数反转
- 4.回文数
- 5.罗马数字转十进制整数
- 6.无重复字符的最长字串
- 7.最长公共前缀
- 8.有效的括号
- 9.合并两个链表
- 二、数组
- 1、删除排序数组中的重复项
- 2.买卖股票的最佳时机
- 3.旋转数组
- 4.存在重复
- 5.只出现一次的数字
- 6.两个数组的交集
- 7.加一
- 8.移动零
- 9.两数之和
- 10.有效的数独
- 三、字符串
- 1.反转字符串
- 2.字符串中的第一个唯一字符
- 3.有效的字母异位词
一,初次尝试
1.两数之和
给定一个整数数组 nums
和一个目标值 target
,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
我的编程:
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] result = new int[2];
for(int i=0;i<nums.length;i++){
for(int j=nums.length-1;j>i;j--){
if(nums[j]+nums[i]==target){
result[0] = i;
result[1] = j;
return result;
}
}
}
return null;
}
}
10ms范例:
class Solution {
public int[] twoSum(int[] nums, int target) {
HashMap<Integer,Integer> s = new HashMap(nums.length);
int i;
Integer temp;
for (i=0;i<nums.length;++i)
s.put(nums[i],i);
//有逻辑bug
for (i=0;i<nums.length;++i)
{
temp = s.get(target-nums[i]);
if (temp!=null && temp!=i)
return new int[]{i,temp};
}
return new int[]{0,0};
}
}
2.两数相加
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
失败
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* } 我现在了解了这个集合,一个成员变量,一个自对象,一个构造函数。但是他是如何存储多位的?
arrayslist linkedlist hashmap ,,如果是通过下表遍历首选arraylist 如果是通过首位末尾操作,首选linkedlist 而hashmap对于键值对的查询较为便利。
*/
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
}
}
3.整数反转
给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
class Solution {
/**
如何处理符号问题,如何处理溢出问题,如何处理数据转换问题
*/
public int reverse(int x) {
String s = Integer.valueOf(x).toString();
String k = "";
String t = "-";
if(s.startsWith(t)){
k="-";
s = s.substring(1);
}
for(int i=s.length()-1;i>=0;i--){
if(s.charAt(i)==0) continue;
k += s.charAt(i);
}
long l = Long.parseLong(k);
int b ;
if(l>Integer.MAX_VALUE||l<Integer.MIN_VALUE){
b = 0;
}else{
b = Integer.parseInt(k);
}
return b;
}
}
另一种思路
public int reverse(int x) {
int rev = 0;
while (x != 0) {
int pop = x % 10;
x /= 10;
if (rev > Integer.MAX_VALUE/10 || (rev == Integer.MAX_VALUE / 10 && pop > 7)) return 0;
if (rev < Integer.MIN_VALUE/10 || (rev == Integer.MIN_VALUE / 10 && pop < -8)) return 0;
rev = rev * 10 + pop;
}
return rev;
}
特别的判断方法
class Solution {
public int reverse(int x) {
int ret = 0;
while(x != 0) {
int temp = ret*10 + x%10;
if(temp / 10 != ret)
return 0;
ret = temp;
x /= 10;
}
return ret;
}
}
4.回文数
class Solution {
public boolean isPalindrome(int x) {
int[] a = new int[12];
int i = 0;
if(x <0){
return false;
}
do{
a[i] = x%10;
x = x/10;
i++;
}while(x!=0);
for(int j=0,k=i-1;j<i/2;j++,k--){
if(a[j]!=a[k]){
return false;
}
}
return true;
}
}
5.罗马数字转十进制整数
class Solution {
public int romanToInt(String s) {
s=s+' ';
int x = 0;
/*一般情况:
字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
特殊情况:
I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900
*/
for(int i=0;i<s.length();i++){
if(s.charAt(i)=='M'){
x=x+1000;
}else if(s.charAt(i)=='D'){
x=x+500;
}else if(s.charAt(i)=='C'&&s.charAt(i+1)=='M'){
x=x+900;
i++;
}else if(s.charAt(i)=='C'&&s.charAt(i+1)=='D'){
x=x+400;
i++;
}else if(s.charAt(i)=='C'){
x=x+100;
}else if(s.charAt(i)=='L'){
x=x+50;
}else if(s.charAt(i)=='X'&&s.charAt(i+1)=='C'){
x=x+90;
i++;
}else if(s.charAt(i)=='X'&&s.charAt(i+1)=='L'){
x=x+40;
i++;
}else if(s.charAt(i)=='X'){
x=x+10;
}else if(s.charAt(i)=='V'){
x=x+5;
}else if(s.charAt(i)=='I'&&s.charAt(i+1)=='X'){
x=x+9;
i++;
}else if(s.charAt(i)=='I'&&s.charAt(i+1)=='V'){
x=x+4;
i++;
}else if(s.charAt(i)=='I'){
x++;
}else if(s.charAt(i)==' '){
break;
}else {
return -1;
}
}
return x;
}
}
/*集合方式*/
class Solution {
public int romanToInt(String s) {
int result = 0;
Map<Character, Integer> map = getMapRoman();
char[] sArray = s.toCharArray();
int i=0, j=1;
for(;i<sArray.length-1;i++, j++){
if(map.get(sArray[i]) >= map.get(sArray[j])){
result += map.get(sArray[i]);
}else{
result -= map.get(sArray[i]);
}
}
result += map.get(sArray[i]);
return result;
}
public static Map<Character, Integer> getMapRoman() {
Map<Character, Integer> map = new HashMap<>();
map.put('I', 1);
map.put('V', 5);
map.put('X', 10);
map.put('L', 50);
map.put('C', 100);
map.put('D', 500);
map.put('M', 1000);
return map;
}
}
6.无重复字符的最长字串
/*为解决测试用例超时问题*/
class Solution {
public int lengthOfLongestSubstring(String s) {
HashMap<Integer,String> map = new HashMap<>();
String t;
for(int i=0;i<s.length();i++){
for(int j=s.length();j>i;j--){
t = s.substring(i,j);
if(unRepetition(t)){
map.put(t.length(),t);
}
}
}
return map.size();
}
public boolean unRepetition(String s){
for(int i=0;i<s.length();i++){
for(int j=i+1;j<s.length();j++){
if(s.charAt(i)==s.charAt(j)){
return false;
}
}
}
return true;
}
}
/*成功用例*/
class Solution {
public int lengthOfLongestSubstring(String s) {
if(s == null || s.length() == 0) {
return 0;
}
int max = 0;
Set<Character> set = new HashSet<>();
int i = 0, j = 0;
while(i<s.length()&&j<s.length()) {
if(!set.contains(s.charAt(j))) {
set.add(s.charAt(j++));
max = Math.max(j-i,max);
}else {
set.remove(s.charAt(i++));
}
}
return max;
}
}
//第二种
class Solution {
public int lengthOfLongestSubstring(String s) {
char[] chas=s.toCharArray();
int max=0;
int[] n=new int[128];
for(int i=0,j=0;j<chas.length;j++){
i=Math.max(n[chas[j]],i);
max=Math.max(max,j-i+1);
n[chas[j]]=j+1;
}
return max;
}
}
//我使用的方法的变种
class Solution {
public int lengthOfLongestSubstring(String s) {
int len = s.length();
int childLen = 0;
Map<Character, Integer> map = new HashMap<>();
for (int i = 0, j = 0; j < len; j++) {
if (map.containsKey(s.charAt(j))) {
i = Math.max(map.get(s.charAt(j)), i);
}
childLen = Math.max(childLen, j - i + 1);
map.put(s.charAt(j), j + 1);
}
return childLen;
}
}
7.最长公共前缀
/*编写一个函数来查找字符串数组中的最长公共前缀;
如果不存在公共前缀,返回空字符串 "";所有输入只包含小写字母 a-z 。*/
class Solution {
public String longestCommonPrefix(String[] strs) {
String s=strs[0];
String t="";
for(int i=1;i<strs.length;i++){
int j=0;
while(j<Math.min(s.length(),strs[i].length())){
if(strs[i-1].charAt(j)==strs[i].charAt(j)){
t=t+strs[i].charAt(j);
}else{
break;
}
j++;
}
s=s.length()>t.length()?t:s;
t="";
if(s.equals("")){
return "";
}
}
return s;
}
}
/*截断字符法*/
class Solution {
public String longestCommonPrefix(String[] strs) {
if(strs==null||strs.length==0)
return "";
for(int i=0;i<strs[0].length();i++){
char c=strs[0].charAt(i);
for(int j=0;j<strs.length;j++)
if(i==strs[j].length()||strs[j].charAt(i)!=c)
return strs[0].substring(0,i);
}
return strs[0];
8.有效的括号
/**给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
分析:字符串长度一定是偶数;左右括号的个数必须相同;括号的顺序有一定的要求;不同括号交叉会有出错的风险
偶数好办,个数相同就采用计数方式;括号的顺序有要求---就采用左加右减的操作--判断数为非负数;括号之间交叉:
将有效的括号进行删除,如果括号之间有非法交叉,那么就会导致整体括号对不再完整,返回false
收获:我所考虑的顺序问题,其实归根结底就是下一个右括号和上一个左括号的类型不匹配,计算机不会直观的顺序阅读,他们只考虑匹配。
java提供的堆栈
*/
class Solution {
private HashMap<Character,Character> mappings;
public Solution() {
this.mappings = new HashMap<Character, Character>();
this.mappings.put(')','(');
this.mappings.put('}','{');
this.mappings.put(']','[');
}
public boolean isValid(String s) {
Stack<Character> stack = new Stack<Character>();
for(int i = 0; i<s.length(); i++){
char c = s.charAt(i);
//"(([(])))"
if(this.mappings.containsKey(c)) {
char topElement = stack.empty() ? '#' : stack.pop();
if(topElement != this.mappings.get(c)){
return false;
}
}else {
stack.push(c);
}
}
return stack.isEmpty();
}
}
/*复杂方法,可能和我想的方法相同*/
class Solution {
public boolean isValid(String s) {
int topIndex = -1;
char[] stack = new char[s.length()];
for (int i = 0; i < s.length(); i++) {
char c1 = s.charAt(i);
switch (c1) {
case 40:
stack[++topIndex] = c1;
continue;
case 91:
stack[++topIndex] = c1;
continue;
case 123:
stack[++topIndex] = c1;
continue;
}
if (topIndex < 0) {
return false;
}
switch (stack[topIndex] + c1) {
case 81:
topIndex--;
continue;
case 184:
topIndex--;
continue;
case 248:
topIndex--;
continue;
default:
return false;
}
}
return topIndex == -1;
}
}
9.合并两个链表
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* }
* }
*/
class Solution {
/*这是个链表,创建的是链表,类似于数组,也许没有下标,但是可以相对遍历很多个元素,这个链表可以调用next对象,next对象又是一个相对来说小的链表,类似于LinkedList,LinkedList是一个有首尾的圆形链表,这个是只有开头的直线链表,这个链表和List类的链表不同,他没有继承List类(或者是接口),没办法使用迭代器。*/
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode res = new ListNode(0);
ListNode re = res;
int t = 0;
if(l1 == null && l2 == null){
res = null;
return res;
}
while (l1!=null || l2!=null) {
if (l1 == null) {
t = l2.val;
l2 = l2.next;
} else if(l2 == null){
t = l1.val;
l1 = l1.next;
} else if(l2.val >= l1.val){
t = l1.val;
l1 = l1.next;
} else{
t = l2.val;
l2 = l2.next;
}
re.val = t;
if(l1 == null && l2 == null)
break;
re.next = new ListNode(0);
re = re.next;
}
return res;
}
}
二、数组
1、删除排序数组中的重复项
/*给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。*/
/*如何处理重复项,置为null值
i
[1,2,1,2,2,2,3]
j
*/
class Solution {
public int removeDuplicates(int[] nums) {
int i = 0;
int j = 1;
if (nums.length==0||nums==null){
return 0;
}
while (j<nums.length){
if (nums[i]==nums[j]){
j++;
} else{
nums[i+1] = nums[j];
i++;
j++;
}
}
return i+1;
}
}
2.买卖股票的最佳时机
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
/*多种组合
i
[7,1,5,6,8,7,3,6,7,4,1,5,6,8]
j
这个题的关键应该寻找一组组数据,寻找最优化数据组来使得每组数据差的总和最大
*/
class Solution {
public int maxProfit(int[] prices) {
int count=0;
int i = 0;
int j = 1;
while(i<prices.length&&j<prices.length){
if (prices[i]>prices[i+1]){
i++;
j++;
continue;
}
if (j==prices.length-1){
count += prices[j]-prices[i];
return count;
}
if (prices[j]<prices[j+1]){
j++;
continue;
} else{
count += prices[j]-prices[i];
i = j+1;
j = i+1;
}
}
return count;
}
}
其他人的方法
class Solution {
public int maxProfit(int[] prices) {
if(prices==null || prices.length<=1) return 0;
int i=0;
int valley=prices[0];
int peak=prices[0];
int maxprofit=0;
while(i<prices.length-1){
while(i<prices.length-1 && prices[i]>=prices[i+1]){
i++;
}
valley=prices[i];//gu
while(i<prices.length-1 && prices[i]<=prices[i+1]){
i++;
}
peak=prices[i];//feng
maxprofit +=peak-valley;
}
return maxprofit;
}
}
3.旋转数组
给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
输入: [1,2,3,4,5,6,7] 和 k = 3
输出: [5,6,7,1,2,3,4]
/*
i
[1,2,3,4,5,6,7]
3
[ ]
*/
class Solution {
public void rotate(int[] nums, int k) {
int[] res = new int[nums.length];
int j = 0;
for(int i=0;i<nums.length;i++){
j = k+i;
while(j>nums.length-1){
j = j-nums.length;
}
res[j] = nums[i];
}
nums = res;
}
}
class Solution {
public void rotate(int[] nums, int k) {
k=k%nums.length;
int[] tmp=nums.clone();
System.arraycopy(tmp,tmp.length-k,nums,0,k);
System.arraycopy(tmp,0,nums,k,tmp.length-k);
}
}
4.存在重复
给定一个整数数组,判断是否存在重复元素。
如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。
class Solution {
public boolean containsDuplicate(int[] nums) {
Arrays.sort(nums);
for(int i=0;i<nums.length-1;i++){
if(nums[i]==nums[i+1]){
return true;
}
}
return false;
}
}
5.只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
/*
[1,1,2,2,2,2,3,4,4,5,5]
*/
class Solution {
public int singleNumber(int[] nums) {
Arrays.sort(nums);
for(int i=0;i<nums.length-1;i+=2){
if(nums[i]!=nums[i+1]){
return nums[i];
}
}
return nums[nums.length-1];
}
}
class Solution {
public int singleNumber(int[] nums) {
int single = 0;
for(int i = 0;i < nums.length; i++){
single = single ^ nums[i];
}
return single;
}
}
6.两个数组的交集
给定两个数组,编写一个函数来计算他们的交集
class Solution {
public int[] intersect(int[] nums1, int[] nums2) {
Arrays.sort(nums1);
Arrays.sort(nums2);
int i=0;
int j=0;
int n=0;
int[] res = new int[Math.min(nums1.length,nums2.length)];
while(i<nums1.length&&j<nums2.length){
if(nums1[i]==nums2[j]){
res[n] = nums1[i];
i++;
j++;
n++;
} else if(nums1[i]<nums2[j]){
i++;
} else{
j++;
}
}
return res;
}
}
7.加一
给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。
最高位数字存放在数组的首位, 数组中每个元素只存储一个数字。
你可以假设除了整数 0 之外,这个整数不会以零开头。
/*处理9999*/
class Solution {
public int[] plusOne(int[] digits) {
int l = digits.length;
for(int i=l-1;i>=0;i--){
if(digits[i]!=9){
digits[i]++;
return digits;
}
digits[i] = 0;
}
digits = new int[l+1];
digits[0] = 1;
return digits;
}
}
8.移动零
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
i
[0,1,0,3,12]
j
/*冒泡排序的阉割版*/
class Solution {
public void moveZeroes(int[] nums) {
if(){
}
int i = 0;
int j = 1;
while(j<nums.length&&i<j){
if{
}
if (nums[i]==0) {
if (nums[j]!=0) {
nums[i] = nums[j];
nums[j] = 0;
i++;
j++;
} else{
j++;
}
} else{
i++;
j++;
}
}
}
}
9.两数之和
给定一个整数数组 nums和一个目标值 target, 请你在该数组中找出和为目标值的那 两个整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
/*
nums = [2, 7, 11, 15], target = 9
*/
垃圾求和方式,这是垃圾
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] res = new int[2];
for(int i=0;i<nums.length-1;i++){
for(int j=i+1;j<nums.length-1;j++){
if(nums[i]+nums[j]==target){
res[0] = i;
res[1] = j;
return res;
}
}
}
return res;
}
}
//HashMap方式
class Solution {
public int[] twoSum(int[] nums, int target) {
int ss = 0;
HashMap<Integer,Integer> map = new HashMap<>();
for(int i=0;i<nums.length;i++){
ss = target - nums[i];
if(map.containsKey(ss)){
return new int[]{map.get(ss),i};
}
map.put(nums[i],i);
}
return null;
}
}
10.有效的数独
判断一个 9x9 的数独是否有效。只需要根据以下规则,验证已经填入的数字是否有效即可。
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
说明:
一个有效的数独(部分已被填充)不一定是可解的。
只需要根据以上规则,验证已经填入的数字是否有效即可。
给定数独序列只包含数字 1-9 和字符 '.' 。
给定数独永远是 9x9 形式的。
/*
如何处理二维数组,二维数组的行是一个数组,列用来遍历行数组。
*/
class Solution {
public boolean isValidSudoku(char[][] board) {
HashSet<Character> set = new HashSet<>();
for (int i=0;i<board.length;i++) {
for(int j=0;j<char[i][].length;j++){
if(char[i][j].equals('.')){
continue;
}
if(set.contains(char[i][j])){
return false;
}
set.put(char[i][j]);
}
set.clear();
}
for (int i=0;i<board.length;i++) {
for(int j=0;j<char[][i].length;j++){
if(char[j][i].equals('.')){
continue;
}
if(set.contains(char[j][i])){
return false;
}
set.put(char[j][i]);
}
set.clear();
}
return true;
}
}
/*渣渣,看别人是咋写的*/
class Solution {
public boolean isValidSudoku(char[][] board) {
boolean[][] row = new boolean[9][9];
boolean[][] col = new boolean[9][9];
boolean[][][] grid = new boolean[3][3][9];
for(int i=0; i<9; i++){
for(int j=0; j<9; j++){
if(board[i][j] == '.')continue;
int n = board[i][j] - 49;
if(row[i][n] || col[j][n] || grid[i/3][j/3][n]) return false;
row[i][n] = true;
col[j][n] = true;
grid[i/3][j/3][n] = true;
}
}
return true;
}
}
三、字符串
####1.反转字符串
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。
/*
i
["h","e","l","l","o"]
j
*/
class Solution {
public void reverseString(char[] s) {
char c = '';
for (int i=0,j=s.length-1;i<j;i++,j-- ) {
c = s[i];
s[i] = s[j];
s[j] = c;
}
}
}
####2.字符串中的第一个唯一字符
给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,
返回-1
class Solution {
public int firstUniqChar(String s) {
HashMap<Character,Integer> map = new HashMap<>();
int j = 0;
char c = ' ';
return j;
}
}
class Solution {
public int firstUniqChar(String s){
char []cs = s.toCharArray();
char []record = new char[26];
int index = 0;
//统计
for (char c : cs) {
record[c - 'a']++;
}//这句话就是用来统计的,比如出现了字符为a,那么a-a就是0,在数组record[0]自增,这个位置的记录就变成了1
//判断
//下面是错误写法
// for (int i = 0; i < record.length; i++) { //这里不能用record,因为record有的位置是用的,如果z出现一次,i为26,返回的是26而不是String中字符的位置
// if (record[i] == 1) {
// return i;
// }
// }
for (int i = 0; i < cs.length; i++) {
if (record[cs[i] - 'a'] == 1) {
return i;
}
}
return -1;
}
}
这是最简单的方法
class Solution {
public int firstUniqChar(String s) {
int res = -1;
for(char ch = 'a'; ch <= 'z'; ch++){
int index = s.indexOf(ch);
if(index != -1 && index == s.lastIndexOf(ch)){
res = (res == -1 || res > index) ? index : res;
}
}
return res;
}
}
####3.有效的字母异位词
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的一个字母异位词。
说明:
你可以假设字符串只包含小写字母。
class Solution {
public boolean isAnagram(String s, String t) {
if (s.length != t.length) {
return false;
}
char[] sh = s.toCharArray();
char[] th = t.toCharArray();
char c = ' ';
HashMap<Character,Integer> map = HashMap<>();
for (int i=0;i<sh.length;i++ ) {
c = sh[i]
if (map.containsKey(c)) {
map.put(c,map.get()++)
} else {
map.put(c,1);
}
}
for (int i=0;i<th.length;i++ ) {
c = th[i]
if (map.containsKey(c)) {
map.put(c,map.get()--)
if(map.get(c)==0){
map.remove(c);
}
} else {
return false;
}
}
if (map.size == 0) {
return true;
}
return false;
}
}
//其他方法
class Solution {
public boolean isAnagram(String s, String t) {
if (s.length() != t.length()) {
return false;
}
int[] chars = new int[26];
for(int i=0;i<s.length();i++){
chars[s.charAt(i)-'a']++;
chars[t.charAt(i)-'a']--;
}
for(int c:chars){
if(c!=0){
return false;
}
}
return true;
}
}