- 两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
解:
初步认为是2个指针问题,第一个为i,第二个为i+1。穷举一下就完事了
public int[] TwoSum(int[] nums, int target)
{
int[] ans = new int[] { 0,0};
int len = nums.Length;
for (int i = 0; i < len; i++)
{
int l = nums[i];
for (int j = i+1; j < len; j++)
{
int r = nums[j];
if(l+r == target)
{
ans[0] = i;
ans[1] = j;
return ans;
}
}
}
return ans;
}
但这似乎效率很低 时间复杂度为O(nXn)
看了题解,所要求为找到值为 target-nums[i]的数,那么,用一个字典缓存下即可解决。时间复杂度为nX(hash 表的效率)
public int[] TwoSum(int[] nums, int target)
{
int[] ans = new int[] { 0, 0};
int len = nums.Length;
Dictionary<int, int> dic = new Dictionary<int, int>();
List<int> local = new List<int>();
for (int i = 0; i < len; i++)
{
int v = nums[i];
var dif = target - v;
if(dic.ContainsKey(dif))
{
ans[0] = i;
ans[1] = dic[dif];
return ans;
}
else
{
dic[v] = i;
}
}
return ans;
}
- 两数相加
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
这个题目比前一个要复杂,2个指针的都复杂。
对于这种有next节点的单链表,初始化起来会麻烦一些。可以声明一个虚拟头节点,用完之后舍弃它。
public static ListNode FormListNode(int[] ary)
{
ListNode dump = new ListNode(0, null);
ListNode f = dump;
for (int i = 0; i < ary.Length; i++)
{
dump.next = new ListNode(ary[i], null);
dump = dump.next;
}
return f.next;
}
第一次的提交为
public ListNode AddTwoNumbers(ListNode l1, ListNode l2)
{
ListNode dump = new ListNode(0,null);
ListNode first = dump;
int pre = 0;
while(true)
{
int l = (l1 != null) ? l1.val : 0;
int r = (l2 != null) ? l2.val : 0;
int v = l + r+pre;
int cur = v % 10;
pre = v >= 10 ? 1 : 0;
ListNode node = new ListNode(cur,null);
dump.next = node;
dump = dump.next;
if(l1!=null)
{
l1 = l1.next;
}
if(l2!=null)
{
l2 = l2.next;
}
if (l1 == null && l2 == null)
{
break;
}
}
if(pre>0)
{
ListNode node = new ListNode(pre, null);
dump.next = node;
dump = dump.next;
}
return first.next;
}
提交通过了,但是效率应该有些问题。就这样吧
- 无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度
开始的时候想简单了
public int LengthOfLongestSubstring(string s)
{
int len = s.Length;
List<char> tmp = new List<char>();
int max = 0;
for (int i = 0; i < len; i++)
{
var ti = s[i];
if(!tmp.Contains(ti))
{
tmp.Add(ti);
}
else
{
if(tmp.Count>max)
{
max = tmp.Count;
}
tmp.Clear();
tmp.Add(ti);
}
}
if (tmp.Count > max)
{
max = tmp.Count;
}
return max;
}
这样妥妥的错误。测试用例 "dvdf"这样输出的结果居然是2。 思路都不对。
对于循环
a 考虑循环开始
b 考虑循环中
c 考虑循环结束
其中 循环中是错误的。当tmp包含ti时,应该考虑
修改后为:
public int LengthOfLongestSubstring(string s)
{
int len = s.Length;
List<char> tmp = new List<char>();
int max = 0;
for (int i = 0; i < len; i++)
{
var ti = s[i];
if(!tmp.Contains(ti))
{
tmp.Add(ti);
}
else
{
if(tmp.Count>max)
{
max = tmp.Count;
}
for (int j = 0; j < tmp.Count; j++)
{
if(ti == tmp[j])
{
tmp.RemoveRange(0, j + 1);
break;
}
}
tmp.Add(ti);
}
}
if (tmp.Count > max)
{
max = tmp.Count;
}
return max;
}
这次正确了。
可以理解为 这是一个滑动窗口,这个窗口一格一格的向前滑动,每滑动一步都保证窗口的值符合要求。
- 寻找两个正序数组的中位数
给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
这个题目困难一些。有2个数组,需要2个指针,在取数的时候需要判断是否到了数组末尾。
第一次提交
public double FindMedianSortedArrays(int[] nums1, int[] nums2)
{
int l = 0;
int r = 0;
int lp = 0;
int rp = 0;
int cur = 0;
int idx = 0;
int total = nums1.Length + nums2.Length;
double ans = 0;
if(total%2 ==0)
{
l = total / 2-1;
r = l + 1;
}
else
{
l = (total-1) / 2-1;
r = l + 2;
}
while(true)
{
int num = 0;
if(lp>=nums1.Length)
{
num = nums2[rp++];
}
else if(rp>=nums2.Length)
{
num = nums1[lp++];
}
else
{
if(nums1[lp]<=nums2[rp])
{
num = nums1[lp++];
}
else
{
num = nums2[rp++];
}
}
if(idx==l)
{
cur = num;
}
if(idx==r)
{
ans = (cur + num) / 2.0d;
break;
}
idx++;
}
return ans;
}
果然错了,没有考虑到临近条件。两个数组都可能为空的。
处理边界非常麻烦,按照这个思路需要一坨的代码。
各种错误,思路不对重新整理。
这个题目主要按我的理解主要是各种临界条件很难考虑全面。
public double FindMedianSortedArrays(int[] nums1, int[] nums2)
{
int r = 0;
int lp = 0;
int rp = 0;
int pre = 0;
int idx = 0;
int l1Len = nums1.Length;
int l2Len = nums2.Length;
int total = l1Len + l2Len;
bool isOdd = total % 2 != 0;
double dv = 2.0d;
double ans = 0;
if(total == 0)
{
return 0;
}
else if(isOdd)
{
r = (total - 1) / 2;
}
else
{
r = total / 2;
}
while(true)
{
int num = 0;
if (lp >= l1Len)
{
if (rp >= l2Len)
{
num = 0;
}
else
{
num = nums2[rp++];
}
}
else if(rp>= l2Len)
{
if(lp>= l1Len)
{
num = 0;
}
else
{
num = nums1[lp++];
}
}
else
{
if (nums1[lp] <= nums2[rp])
{
num = nums1[lp++];
}
else
{
num = nums2[rp++];
}
}
if(idx>=r)
{
if(isOdd)
{
ans = num;
}
else
{
ans = (num + pre) / dv;
}
break;
}
pre = num;
idx++;
}
return ans;
}
这次提交通过了思路:
取左面数组的数还是取右面数组的数需要严格按照条件判定。
取值完了之后需要按照奇数还是偶数求值。